diff --git a/scripts/harmonize-unit-sprites.py b/scripts/harmonize-unit-sprites.py index 68e52fc..68ff01e 100644 --- a/scripts/harmonize-unit-sprites.py +++ b/scripts/harmonize-unit-sprites.py @@ -314,14 +314,8 @@ def stabilize_palette_image(image: Image.Image) -> Image.Image: image = image.convert("RGBA") red, green, blue, alpha = image.split() rgb = Image.merge("RGB", (red, green, blue)) - rgb = ImageEnhance.Color(rgb).enhance(0.76) - rgb = ImageEnhance.Contrast(rgb).enhance(0.97) - rgb = ImageEnhance.Brightness(rgb).enhance(0.98) - - luma = ImageOps.grayscale(rgb) - battlefield = ImageOps.colorize(luma, black=(22, 20, 22), white=(210, 194, 158), mid=(104, 91, 73)) - tone_mask = alpha.point(lambda value: min(46, round(value * 0.16))) - rgb = Image.composite(battlefield, rgb, tone_mask) + rgb = ImageEnhance.Contrast(rgb).enhance(1.01) + rgb = ImageEnhance.Brightness(rgb).enhance(1.0) return Image.merge("RGBA", (*rgb.split(), alpha)) @@ -552,29 +546,29 @@ def colored_mask(alpha: Image.Image, color: tuple[int, int, int, int]) -> Image. def style_for_unit(stem: str) -> UnitStyle: lower = stem.lower() scale = 0.98 - saturation = 0.9 + saturation = 1.0 contrast = 1.04 - brightness = 0.98 - edge_warmth = 0.68 + brightness = 1.0 + edge_warmth = 0.9 rim_color = (31, 25, 35) if any(token in lower for token in ("archer", "crossbow", "longbow")): scale = 0.94 - saturation = 0.88 + saturation = 1.0 elif any(token in lower for token in ("cavalry", "ma-chao", "ma-dai", "lu-bu")): scale = 1.03 contrast = 1.05 elif any(token in lower for token in ("strategist", "shaman", "zhuge", "sima", "fa-zheng", "ma-liang", "yi-ji")): scale = 0.93 - brightness = 0.99 + brightness = 1.0 rim_color = (29, 28, 41) elif any(token in lower for token in ("leader", "officer", "meng-huo", "guan-yu", "zhang-fei", "jiang-wei")): scale = 1.01 contrast = 1.05 - edge_warmth = 0.78 + edge_warmth = 0.98 if "nanman" in lower or "meng-huo" in lower: - saturation = 0.92 + saturation = 1.0 rim_color = (38, 28, 34) elif "wu-" in lower or "lu-meng" in lower: rim_color = (25, 31, 37) diff --git a/scripts/redraw-unit-sprites.py b/scripts/redraw-unit-sprites.py new file mode 100644 index 0000000..c5ef505 --- /dev/null +++ b/scripts/redraw-unit-sprites.py @@ -0,0 +1,621 @@ +from __future__ import annotations + +import argparse +import colorsys +import hashlib +import math +from dataclasses import dataclass +from pathlib import Path + +from PIL import Image, ImageChops, ImageDraw, ImageEnhance, ImageFilter + + +FRAME_SIZE = 313 +GRID_SIZE = 4 +PALETTE_COLORS = 224 +ROOT = Path(__file__).resolve().parents[1] +UNIT_DIR = ROOT / "src" / "assets" / "images" / "units" +SOURCE_ATLAS = ROOT / "src" / "assets" / "images" / "unit-sources" / "three-kingdoms-unit-atlas.png" + +DIRECTIONS = ("south", "east", "north", "west") +ACTION_ORDER = ("attack", "strategy", "item", "hurt") + + +@dataclass(frozen=True) +class Template: + atlas_index: int + role: str + target_height: int + target_width: int + + +@dataclass(frozen=True) +class UnitPlan: + template: str + tint: tuple[int, int, int] + tint_strength: float + saturation: float = 1.0 + brightness: float = 1.0 + scale: float = 1.0 + + +TEMPLATES: dict[str, Template] = { + "shu-lord": Template(0, "infantry", 296, 284), + "green-polearm": Template(1, "polearm", 300, 292), + "red-spear": Template(2, "polearm", 296, 292), + "white-cavalry": Template(3, "cavalry", 304, 302), + "wei-lord": Template(4, "infantry", 296, 284), + "red-cavalry": Template(5, "cavalry", 304, 302), + "strategist": Template(6, "strategist", 288, 270), + "rebel-infantry": Template(7, "infantry", 290, 278), + "rebel-archer": Template(8, "archer", 286, 284), + "rebel-cavalry": Template(9, "cavalry", 304, 302), + "wu-officer": Template(10, "infantry", 292, 282), + "nanman-officer": Template(11, "polearm", 294, 286), +} + +SIGNATURE_PLANS: dict[str, UnitPlan] = { + "unit-liu-bei": UnitPlan("shu-lord", (42, 142, 72), 0.04, 1.04, 1.02, 1.0), + "unit-guan-yu": UnitPlan("green-polearm", (34, 132, 70), 0.04, 1.03, 1.02, 1.0), + "unit-zhang-fei": UnitPlan("red-spear", (152, 42, 42), 0.05, 1.04, 1.02, 1.0), + "unit-zhao-yun": UnitPlan("white-cavalry", (42, 116, 184), 0.06, 1.04, 1.03, 1.0), + "unit-cao-cao": UnitPlan("wei-lord", (52, 58, 122), 0.06, 1.02, 1.01, 1.0), + "unit-lu-bu": UnitPlan("red-cavalry", (140, 36, 54), 0.05, 1.05, 1.02, 1.0), + "unit-zhuge-liang": UnitPlan("strategist", (42, 126, 118), 0.05, 1.02, 1.03, 1.0), + "unit-pang-tong": UnitPlan("strategist", (80, 126, 68), 0.09, 1.02, 1.0, 0.98), + "unit-sima-yi": UnitPlan("strategist", (58, 62, 132), 0.16, 1.04, 0.96, 1.0), + "unit-huang-zhong": UnitPlan("rebel-archer", (54, 124, 64), 0.28, 1.04, 1.02, 1.0), + "unit-ma-chao": UnitPlan("white-cavalry", (54, 118, 194), 0.1, 1.04, 1.04, 1.0), + "unit-ma-dai": UnitPlan("white-cavalry", (98, 122, 156), 0.22, 1.02, 0.98, 1.0), + "unit-meng-huo": UnitPlan("nanman-officer", (192, 88, 42), 0.1, 1.04, 1.02, 1.0), + "unit-jiang-wei": UnitPlan("green-polearm", (44, 140, 124), 0.18, 1.04, 1.02, 1.0), + "unit-wei-yan": UnitPlan("green-polearm", (132, 42, 58), 0.28, 1.05, 0.98, 1.0), +} + +FACTION_TINTS = { + "shu": (42, 142, 76), + "wei": (64, 72, 150), + "wu": (28, 132, 142), + "nanman": (188, 88, 42), + "rebel": (202, 150, 36), +} + + +def main() -> None: + parser = argparse.ArgumentParser(description="Redraw unit sprite sheets from a high-quality generated source atlas.") + parser.add_argument("--only", help="Comma-separated unit stems or filenames to redraw.") + parser.add_argument("--out-dir", default=str(UNIT_DIR), help="Output directory. Defaults to the project unit asset directory.") + args = parser.parse_args() + + if not SOURCE_ATLAS.exists(): + raise FileNotFoundError(f"Missing source atlas: {SOURCE_ATLAS}") + + output_dir = Path(args.out_dir).resolve() + output_dir.mkdir(parents=True, exist_ok=True) + only = {entry.strip().removesuffix(".png") for entry in args.only.split(",") if entry.strip()} if args.only else set() + atlas_sprites = extract_source_sprites(Image.open(SOURCE_ATLAS).convert("RGBA")) + + stems = [ + path.stem + for path in sorted(UNIT_DIR.glob("unit-*.png")) + if not path.name.endswith("-actions.png") + ] + + written = 0 + for stem in stems: + if only and stem not in only: + continue + plan = unit_plan(stem) + template = TEMPLATES[plan.template] + source = atlas_sprites[template.atlas_index] + source = tint_sprite(source, plan) + sheet = draw_base_sheet(source, template, stem, plan) + save_unit_png(sheet, output_dir / f"{stem}.png") + save_unit_png(draw_action_sheet(sheet, template, stem), output_dir / f"{stem}-actions.png") + written += 2 + + print(f"Redrew {written} unit sprite sheets from {SOURCE_ATLAS}") + + +def extract_source_sprites(atlas: Image.Image) -> list[Image.Image]: + cell_width = atlas.width // 4 + cell_height = atlas.height // 3 + sprites: list[Image.Image] = [] + for index in range(12): + col = index % 4 + row = index // 4 + cell = atlas.crop((col * cell_width, row * cell_height, (col + 1) * cell_width, (row + 1) * cell_height)) + sprite = remove_chroma_key(cell) + bbox = sprite.getbbox() + if not bbox: + raise ValueError(f"Could not extract atlas sprite {index}") + sprite = sprite.crop(expand_box(bbox, sprite.size, 10)) + sprites.append(sprite) + return sprites + + +def remove_chroma_key(image: Image.Image) -> Image.Image: + image = image.convert("RGBA") + pixels = image.load() + width, height = image.size + for y in range(height): + for x in range(width): + red, green, blue, alpha = pixels[x, y] + green_dominance = green - max(red, blue) + is_key_green = green > 158 and red < 118 and blue < 118 and green_dominance > 58 + if is_key_green: + fade = min(255, max(0, round((green_dominance - 58) * 4.8))) + alpha = max(0, alpha - fade) + if alpha <= 18: + pixels[x, y] = (red, green, blue, 0) + continue + if alpha > 0 and green > 150 and red < 132 and blue < 132 and green_dominance > 48: + green = round(max(red, blue) + green_dominance * 0.38) + pixels[x, y] = (red, green, blue, alpha) + + alpha = image.getchannel("A") + alpha = alpha.filter(ImageFilter.MinFilter(3)).filter(ImageFilter.MaxFilter(3)) + red, green, blue, _ = image.split() + cleaned = Image.merge("RGBA", (red, green, blue, alpha.point(lambda value: 0 if value < 9 else value))) + cleaned = despill_key_edges(cleaned) + return remove_detached_artifacts(cleaned) + + +def despill_key_edges(image: Image.Image) -> Image.Image: + image = image.convert("RGBA") + source = image.copy() + src = source.load() + pixels = image.load() + width, height = image.size + for y in range(height): + for x in range(width): + red, green, blue, alpha = src[x, y] + if alpha <= 0: + continue + green_dominance = green - max(red, blue) + if green <= 120 or green_dominance <= 34: + continue + touches_transparency = False + for ny in range(max(0, y - 1), min(height, y + 2)): + for nx in range(max(0, x - 1), min(width, x + 2)): + if src[nx, ny][3] <= 8: + touches_transparency = True + break + if touches_transparency: + break + if not touches_transparency: + continue + green = min(green, max(red, blue) + 18) + pixels[x, y] = (red, green, blue, alpha) + return image + + +def draw_base_sheet(source: Image.Image, template: Template, stem: str, plan: UnitPlan) -> Image.Image: + sheet = Image.new("RGBA", (FRAME_SIZE * GRID_SIZE, FRAME_SIZE * GRID_SIZE), (0, 0, 0, 0)) + fitted = fit_sprite(source, template, plan) + for row, direction in enumerate(DIRECTIONS): + directed = orient_sprite(fitted, direction) + for col in range(GRID_SIZE): + frame = frame_variant(directed, template, stem, direction, col) + sheet.alpha_composite(frame, (col * FRAME_SIZE, row * FRAME_SIZE)) + return sheet + + +def fit_sprite(source: Image.Image, template: Template, plan: UnitPlan) -> Image.Image: + bbox = source.getbbox() + if not bbox: + return source + subject = source.crop(bbox) + width, height = subject.size + target_height = round(template.target_height * plan.scale) + target_width = round(template.target_width * plan.scale) + scale = min(target_width / width, target_height / height, 1.35) + new_size = (max(1, round(width * scale)), max(1, round(height * scale))) + subject = subject.resize(new_size, Image.Resampling.LANCZOS) + subject = subject.filter(ImageFilter.UnsharpMask(radius=0.65, percent=95, threshold=2)) + return subject + + +def orient_sprite(sprite: Image.Image, direction: str) -> Image.Image: + if direction == "west": + return ImageOps_mirror(sprite) + if direction == "north": + return back_variant(sprite) + return sprite + + +def frame_variant(sprite: Image.Image, template: Template, stem: str, direction: str, frame_index: int) -> Image.Image: + canvas = Image.new("RGBA", (FRAME_SIZE, FRAME_SIZE), (0, 0, 0, 0)) + seed = stable_int(f"{stem}:{direction}") + if template.role == "cavalry": + offsets = [(-6, 0), (0, -5), (6, 0), (0, -3)] + else: + offsets = [(-4, 0), (0, -4), (4, 0), (0, -2)] + dx, dy = offsets[frame_index] + if direction == "north": + dx = round(dx * 0.55) + if direction == "west": + dx = -dx + dx += seed % 3 - 1 + bottom = FRAME_SIZE - (4 if template.role == "cavalry" else 3) + left = round((FRAME_SIZE - sprite.width) / 2 + dx) + top = round(bottom - sprite.height + dy) + canvas.alpha_composite(sprite, (left, top)) + return finish_frame(canvas) + + +def draw_action_sheet(base_sheet: Image.Image, template: Template, stem: str) -> Image.Image: + output = Image.new("RGBA", (FRAME_SIZE * len(ACTION_ORDER), FRAME_SIZE * len(DIRECTIONS)), (0, 0, 0, 0)) + frame_by_action = {"attack": 2, "strategy": 0, "item": 1, "hurt": 0} + for row, direction in enumerate(DIRECTIONS): + for col, action in enumerate(ACTION_ORDER): + frame_index = frame_by_action[action] + frame = base_sheet.crop((frame_index * FRAME_SIZE, row * FRAME_SIZE, (frame_index + 1) * FRAME_SIZE, (row + 1) * FRAME_SIZE)).convert("RGBA") + output.alpha_composite(action_frame(frame, template, stem, direction, action), (col * FRAME_SIZE, row * FRAME_SIZE)) + return output + + +def action_frame(frame: Image.Image, template: Template, stem: str, direction: str, action: str) -> Image.Image: + if action == "hurt": + return hurt_frame(frame, direction) + + effect = Image.new("RGBA", frame.size, (0, 0, 0, 0)) + draw = ImageDraw.Draw(effect) + if action == "attack": + draw_attack_effect(draw, template, direction) + body = offset_subject(frame, *direction_offset(direction, 10 if template.role != "cavalry" else 16)) + result = Image.alpha_composite(effect, body) + elif action == "strategy": + draw_strategy_effect(draw) + result = Image.alpha_composite(effect, frame) + else: + draw_item_effect(draw, direction) + result = Image.alpha_composite(frame, effect) + return finish_frame(result) + + +def draw_attack_effect(draw: ImageDraw.ImageDraw, template: Template, direction: str) -> None: + warm = (239, 177, 68, 160) + bright = (255, 237, 184, 205) + red = (178, 52, 42, 132) + if template.role == "archer": + shafts = { + "east": ((122, 132), (286, 98)), + "west": ((191, 132), (27, 98)), + "north": ((170, 179), (135, 35)), + "south": ((143, 112), (180, 283)), + } + start, end = shafts[direction] + line(draw, [start, end], bright, 7) + line(draw, [start, end], red, 3) + draw.polygon(arrow_tip(end, start, 19), fill=bright, outline=(25, 17, 14, 210)) + return + + if template.role == "strategist": + draw_strategy_effect(draw) + return + + arcs = { + "east": ((132, 58, 303, 224), -55, 55), + "west": ((10, 58, 181, 224), 125, 235), + "north": ((50, 14, 267, 182), 204, 336), + "south": ((45, 113, 269, 295), 25, 155), + } + box, start, end = arcs[direction] + draw.arc(box, start=start, end=end, fill=warm, width=17) + inset = (box[0] + 15, box[1] + 15, box[2] - 15, box[3] - 15) + draw.arc(inset, start=start + 4, end=end - 4, fill=bright, width=7) + + +def draw_strategy_effect(draw: ImageDraw.ImageDraw) -> None: + center = (156, 151) + for radius, color, width in ((88, (39, 94, 156, 66), 4), (58, (46, 142, 174, 106), 4), (28, (236, 184, 74, 134), 5)): + draw.ellipse((center[0] - radius, center[1] - radius, center[0] + radius, center[1] + radius), outline=color, width=width) + for angle in range(0, 360, 60): + x = center[0] + math.cos(math.radians(angle)) * 72 + y = center[1] + math.sin(math.radians(angle)) * 72 + draw.polygon([(x, y - 7), (x + 5, y), (x, y + 7), (x - 5, y)], fill=(236, 184, 74, 126)) + + +def draw_item_effect(draw: ImageDraw.ImageDraw, direction: str) -> None: + positions = { + "south": (184, 145), + "east": (220, 146), + "north": (126, 137), + "west": (92, 146), + } + x, y = positions[direction] + draw.rounded_rectangle((x - 20, y - 16, x + 20, y + 20), radius=7, fill=(126, 79, 39, 235), outline=(25, 18, 14, 235), width=3) + line(draw, [(x - 27, y + 1), (x + 27, y + 1)], (226, 178, 72, 196), 4) + draw.ellipse((x - 11, y - 31, x + 11, y - 9), fill=(76, 178, 112, 200), outline=(24, 18, 14, 220), width=2) + + +def hurt_frame(frame: Image.Image, direction: str) -> Image.Image: + dx, dy = direction_offset(direction, -12) + body = offset_subject(frame, dx, dy) + body = ImageEnhance.Color(body).enhance(0.74) + alpha = body.getchannel("A") + red = Image.new("RGBA", body.size, (188, 42, 36, 0)) + red.putalpha(alpha.point(lambda value: min(86, value // 3))) + body = Image.alpha_composite(body, red) + effect = Image.new("RGBA", frame.size, (0, 0, 0, 0)) + draw = ImageDraw.Draw(effect) + cx, cy = (194, 122) if direction in ("west", "north") else (120, 122) + spikes = [(cx, cy - 31), (cx + 9, cy - 9), (cx + 34, cy - 6), (cx + 13, cy + 8), (cx + 23, cy + 31), (cx, cy + 15), (cx - 24, cy + 30), (cx - 14, cy + 7), (cx - 34, cy - 6), (cx - 9, cy - 9)] + draw.polygon(spikes, fill=(232, 176, 72, 190), outline=(138, 31, 31, 220)) + line(draw, [(cx - 38, cy - 34), (cx + 36, cy + 34)], (255, 231, 181, 166), 5) + return finish_frame(Image.alpha_composite(body, effect)) + + +def unit_plan(stem: str) -> UnitPlan: + if stem in SIGNATURE_PLANS: + return SIGNATURE_PLANS[stem] + + faction = infer_faction(stem) + role = infer_role(stem) + tint = FACTION_TINTS[faction] + strength = 0.16 + if faction == "rebel": + strength = 0.12 + if faction == "nanman": + strength = 0.16 + if faction == "shu": + strength = 0.08 + if faction == "wei": + strength = 0.2 + if faction == "wu": + strength = 0.18 + + template_key = template_for(faction, role, stem) + saturation = 1.03 if "veteran" in stem or "elite" in stem or "warlord" in stem else 1.0 + brightness = 1.03 if "white" in stem else 1.0 + scale = 1.02 if "guard" in stem or "elite" in stem or "warlord" in stem else 1.0 + return UnitPlan(template_key, tint, strength, saturation, brightness, scale) + + +def template_for(faction: str, role: str, stem: str) -> str: + if faction == "nanman": + if role == "strategist" or "shaman" in stem: + return "nanman-officer" + return "nanman-officer" if role in {"officer", "cavalry", "polearm"} else "rebel-infantry" + if faction == "wu": + if role == "strategist": + return "strategist" + if role == "cavalry": + return "rebel-cavalry" + if role == "archer": + return "rebel-archer" + return "wu-officer" + if faction == "wei": + if role == "strategist": + return "strategist" + if role == "cavalry": + return "red-cavalry" + if role == "archer": + return "rebel-archer" + return "wei-lord" if role == "officer" else "rebel-infantry" + if faction == "rebel": + if role == "cavalry": + return "rebel-cavalry" + if role == "archer": + return "rebel-archer" + if role == "officer" or role == "polearm": + return "rebel-infantry" + return "rebel-infantry" + + if role == "cavalry": + return "white-cavalry" + if role == "archer": + return "rebel-archer" + if role == "strategist": + return "strategist" + if role == "polearm": + return "green-polearm" + return "shu-lord" if role == "officer" else "green-polearm" + + +def infer_faction(stem: str) -> str: + lower = stem.lower() + if "nanman" in lower or "meng-huo" in lower: + return "nanman" + if lower.startswith("unit-wu-") or "lu-meng" in lower: + return "wu" + if lower.startswith("unit-wei-") or any(token in lower for token in ("cao-cao", "sima-yi")): + return "wei" + if "rebel" in lower or "yellow" in lower or "bandit" in lower: + return "rebel" + return "shu" + + +def infer_role(stem: str) -> str: + lower = stem.lower() + if "cavalry" in lower or any(token in lower for token in ("zhao-yun", "ma-chao", "ma-dai", "lu-bu")): + return "cavalry" + if "archer" in lower or "huang-zhong" in lower or "crossbow" in lower or "longbow" in lower: + return "archer" + if any(token in lower for token in ("strategist", "shaman", "zhuge", "sima", "fa-zheng", "ma-liang", "yi-ji", "pang-tong")): + return "strategist" + if "spearman" in lower or any(token in lower for token in ("guan-yu", "zhang-fei", "jiang-wei", "yan-yan")): + return "polearm" + if "leader" in lower or "officer" in lower or any(token in lower for token in ("liu-bei", "cao-cao", "meng-huo", "wei-yan", "wang-ping", "wu-yi", "li-yan", "huang-quan", "gong-zhi")): + return "officer" + return "infantry" + + +def tint_sprite(image: Image.Image, plan: UnitPlan) -> Image.Image: + image = image.convert("RGBA") + if plan.tint_strength <= 0: + return image + pixels = image.load() + tint_h, tint_s, tint_v = colorsys.rgb_to_hsv(plan.tint[0] / 255, plan.tint[1] / 255, plan.tint[2] / 255) + for y in range(image.height): + for x in range(image.width): + red, green, blue, alpha = pixels[x, y] + if alpha <= 8 or is_skin(red, green, blue) or is_neutral_metal(red, green, blue): + continue + hue, sat, val = colorsys.rgb_to_hsv(red / 255, green / 255, blue / 255) + strength = plan.tint_strength * (0.45 + min(0.55, sat)) + hue = hue * (1 - strength) + tint_h * strength + sat = min(1.0, sat * plan.saturation + tint_s * strength * 0.45) + val = min(1.0, val * plan.brightness + tint_v * strength * 0.08) + nr, ng, nb = colorsys.hsv_to_rgb(hue, sat, val) + pixels[x, y] = (round(nr * 255), round(ng * 255), round(nb * 255), alpha) + return image + + +def back_variant(sprite: Image.Image) -> Image.Image: + result = sprite.copy() + overlay = Image.new("RGBA", result.size, (18, 20, 26, 0)) + overlay.putalpha(result.getchannel("A").point(lambda value: min(48, value // 6))) + result = Image.alpha_composite(result, overlay) + return result + + +def finish_frame(frame: Image.Image) -> Image.Image: + frame = clean_alpha(frame) + alpha = frame.getchannel("A") + if not alpha.getbbox(): + return frame + ink_alpha = ImageChops.subtract(alpha.filter(ImageFilter.MaxFilter(3)), alpha) + rim = Image.new("RGBA", frame.size, (10, 8, 10, 0)) + rim.putalpha(ink_alpha.point(lambda value: min(180, round(value * 0.65)))) + result = Image.new("RGBA", frame.size, (0, 0, 0, 0)) + result.alpha_composite(rim) + result.alpha_composite(frame) + return clean_alpha(result) + + +def clean_alpha(image: Image.Image) -> Image.Image: + image = image.convert("RGBA") + red, green, blue, alpha = image.split() + alpha = alpha.point(lambda value: 0 if value < 5 else (255 if value > 250 else value)) + return Image.merge("RGBA", (red, green, blue, alpha)) + + +def remove_detached_artifacts(image: Image.Image) -> Image.Image: + alpha = image.getchannel("A") + pixels = alpha.load() + width, height = alpha.size + visited = bytearray(width * height) + components: list[tuple[int, tuple[int, int, int, int], list[tuple[int, int]]]] = [] + for y in range(height): + for x in range(width): + index = y * width + x + if visited[index] or pixels[x, y] <= 8: + continue + stack = [(x, y)] + visited[index] = 1 + points: list[tuple[int, int]] = [] + left = right = x + top = bottom = y + while stack: + px, py = stack.pop() + points.append((px, py)) + left = min(left, px) + right = max(right, px) + top = min(top, py) + bottom = max(bottom, py) + for nx, ny in ((px + 1, py), (px - 1, py), (px, py + 1), (px, py - 1)): + if nx < 0 or nx >= width or ny < 0 or ny >= height: + continue + ni = ny * width + nx + if visited[ni] or pixels[nx, ny] <= 8: + continue + visited[ni] = 1 + stack.append((nx, ny)) + components.append((len(points), (left, top, right + 1, bottom + 1), points)) + if not components: + return image + components.sort(key=lambda component: component[0], reverse=True) + keep_points = set(components[0][2]) + largest_area, largest_bbox, _ = components[0] + for area, bbox, points in components[1:]: + if area >= largest_area * 0.08 or bbox_distance(largest_bbox, bbox) < 12: + keep_points.update(points) + cleaned_alpha = Image.new("L", image.size, 0) + cleaned_pixels = cleaned_alpha.load() + source_pixels = alpha.load() + for x, y in keep_points: + cleaned_pixels[x, y] = source_pixels[x, y] + red, green, blue, _ = image.split() + return Image.merge("RGBA", (red, green, blue, cleaned_alpha)) + + +def expand_box(box: tuple[int, int, int, int], size: tuple[int, int], padding: int) -> tuple[int, int, int, int]: + left, top, right, bottom = box + width, height = size + return (max(0, left - padding), max(0, top - padding), min(width, right + padding), min(height, bottom + padding)) + + +def bbox_distance(left_box: tuple[int, int, int, int], right_box: tuple[int, int, int, int]) -> int: + left_a, top_a, right_a, bottom_a = left_box + left_b, top_b, right_b, bottom_b = right_box + dx = max(left_a - right_b, left_b - right_a, 0) + dy = max(top_a - bottom_b, top_b - bottom_a, 0) + return max(dx, dy) + + +def offset_subject(frame: Image.Image, dx: int, dy: int) -> Image.Image: + canvas = Image.new("RGBA", frame.size, (0, 0, 0, 0)) + bbox = frame.getbbox() + if not bbox: + return frame + subject = frame.crop(bbox) + canvas.alpha_composite(subject, (bbox[0] + dx, bbox[1] + dy)) + return canvas + + +def direction_offset(direction: str, amount: int) -> tuple[int, int]: + if direction == "east": + return amount, 0 + if direction == "west": + return -amount, 0 + if direction == "north": + return 0, -amount + return 0, amount + + +def arrow_tip(end: tuple[float, float], start: tuple[float, float], size: float) -> list[tuple[float, float]]: + ex, ey = end + sx, sy = start + angle = math.atan2(ey - sy, ex - sx) + left = angle + math.radians(150) + right = angle - math.radians(150) + return [ + (ex, ey), + (ex + math.cos(left) * size, ey + math.sin(left) * size), + (ex - math.cos(angle) * size * 0.45, ey - math.sin(angle) * size * 0.45), + (ex + math.cos(right) * size, ey + math.sin(right) * size), + ] + + +def line(draw: ImageDraw.ImageDraw, points: list[tuple[float, float]], fill: tuple[int, int, int, int], width: int) -> None: + draw.line([(round(x), round(y)) for x, y in points], fill=fill, width=width, joint="curve") + + +def is_skin(red: int, green: int, blue: int) -> bool: + return red > 110 and green > 55 and blue > 32 and red > green * 1.1 and green > blue * 1.05 + + +def is_neutral_metal(red: int, green: int, blue: int) -> bool: + return abs(red - green) < 18 and abs(green - blue) < 22 and red > 118 + + +def stable_int(value: str) -> int: + return int(hashlib.sha256(value.encode("utf-8")).hexdigest()[:8], 16) + + +def ImageOps_mirror(image: Image.Image) -> Image.Image: + from PIL import ImageOps + + return ImageOps.mirror(image) + + +def save_unit_png(image: Image.Image, path: Path) -> None: + image = clean_alpha(image) + indexed = image.quantize(colors=PALETTE_COLORS, method=Image.Quantize.FASTOCTREE, dither=Image.Dither.NONE) + indexed.save(path, optimize=True) + + +if __name__ == "__main__": + main() diff --git a/src/assets/images/unit-sources/three-kingdoms-unit-atlas.png b/src/assets/images/unit-sources/three-kingdoms-unit-atlas.png new file mode 100644 index 0000000..527d11f Binary files /dev/null and b/src/assets/images/unit-sources/three-kingdoms-unit-atlas.png differ diff --git a/src/assets/images/units/unit-cao-cao-actions.png b/src/assets/images/units/unit-cao-cao-actions.png index bb1c666..14e1705 100644 Binary files a/src/assets/images/units/unit-cao-cao-actions.png and b/src/assets/images/units/unit-cao-cao-actions.png differ diff --git a/src/assets/images/units/unit-cao-cao.png b/src/assets/images/units/unit-cao-cao.png index a5a96de..0fe38f2 100644 Binary files a/src/assets/images/units/unit-cao-cao.png and b/src/assets/images/units/unit-cao-cao.png differ diff --git a/src/assets/images/units/unit-fa-zheng-actions.png b/src/assets/images/units/unit-fa-zheng-actions.png index 94895c4..8b51510 100644 Binary files a/src/assets/images/units/unit-fa-zheng-actions.png and b/src/assets/images/units/unit-fa-zheng-actions.png differ diff --git a/src/assets/images/units/unit-fa-zheng.png b/src/assets/images/units/unit-fa-zheng.png index dff3078..c1b5e07 100644 Binary files a/src/assets/images/units/unit-fa-zheng.png and b/src/assets/images/units/unit-fa-zheng.png differ diff --git a/src/assets/images/units/unit-gong-zhi-actions.png b/src/assets/images/units/unit-gong-zhi-actions.png index 297516d..82fde58 100644 Binary files a/src/assets/images/units/unit-gong-zhi-actions.png and b/src/assets/images/units/unit-gong-zhi-actions.png differ diff --git a/src/assets/images/units/unit-gong-zhi.png b/src/assets/images/units/unit-gong-zhi.png index 64deeda..1252d7a 100644 Binary files a/src/assets/images/units/unit-gong-zhi.png and b/src/assets/images/units/unit-gong-zhi.png differ diff --git a/src/assets/images/units/unit-guan-yu-actions.png b/src/assets/images/units/unit-guan-yu-actions.png index e0256c0..f7f5fb6 100644 Binary files a/src/assets/images/units/unit-guan-yu-actions.png and b/src/assets/images/units/unit-guan-yu-actions.png differ diff --git a/src/assets/images/units/unit-guan-yu.png b/src/assets/images/units/unit-guan-yu.png index 4133846..f7f20b0 100644 Binary files a/src/assets/images/units/unit-guan-yu.png and b/src/assets/images/units/unit-guan-yu.png differ diff --git a/src/assets/images/units/unit-huang-quan-actions.png b/src/assets/images/units/unit-huang-quan-actions.png index 1675771..8d1239e 100644 Binary files a/src/assets/images/units/unit-huang-quan-actions.png and b/src/assets/images/units/unit-huang-quan-actions.png differ diff --git a/src/assets/images/units/unit-huang-quan.png b/src/assets/images/units/unit-huang-quan.png index cfbf161..9c5a8a0 100644 Binary files a/src/assets/images/units/unit-huang-quan.png and b/src/assets/images/units/unit-huang-quan.png differ diff --git a/src/assets/images/units/unit-huang-zhong-actions.png b/src/assets/images/units/unit-huang-zhong-actions.png index 203485a..d779a3a 100644 Binary files a/src/assets/images/units/unit-huang-zhong-actions.png and b/src/assets/images/units/unit-huang-zhong-actions.png differ diff --git a/src/assets/images/units/unit-huang-zhong.png b/src/assets/images/units/unit-huang-zhong.png index c5c8bf1..4934ac4 100644 Binary files a/src/assets/images/units/unit-huang-zhong.png and b/src/assets/images/units/unit-huang-zhong.png differ diff --git a/src/assets/images/units/unit-jiang-wei-actions.png b/src/assets/images/units/unit-jiang-wei-actions.png index eb5123e..0c1182a 100644 Binary files a/src/assets/images/units/unit-jiang-wei-actions.png and b/src/assets/images/units/unit-jiang-wei-actions.png differ diff --git a/src/assets/images/units/unit-jiang-wei.png b/src/assets/images/units/unit-jiang-wei.png index 24b0a40..11db772 100644 Binary files a/src/assets/images/units/unit-jiang-wei.png and b/src/assets/images/units/unit-jiang-wei.png differ diff --git a/src/assets/images/units/unit-li-yan-actions.png b/src/assets/images/units/unit-li-yan-actions.png index 353b77c..652fa22 100644 Binary files a/src/assets/images/units/unit-li-yan-actions.png and b/src/assets/images/units/unit-li-yan-actions.png differ diff --git a/src/assets/images/units/unit-li-yan.png b/src/assets/images/units/unit-li-yan.png index ee3bdcf..3644f5d 100644 Binary files a/src/assets/images/units/unit-li-yan.png and b/src/assets/images/units/unit-li-yan.png differ diff --git a/src/assets/images/units/unit-liu-bei-actions.png b/src/assets/images/units/unit-liu-bei-actions.png index 04aeb59..22c675e 100644 Binary files a/src/assets/images/units/unit-liu-bei-actions.png and b/src/assets/images/units/unit-liu-bei-actions.png differ diff --git a/src/assets/images/units/unit-liu-bei.png b/src/assets/images/units/unit-liu-bei.png index 715caab..b6852ac 100644 Binary files a/src/assets/images/units/unit-liu-bei.png and b/src/assets/images/units/unit-liu-bei.png differ diff --git a/src/assets/images/units/unit-lu-bu-actions.png b/src/assets/images/units/unit-lu-bu-actions.png index 662ad8e..372713c 100644 Binary files a/src/assets/images/units/unit-lu-bu-actions.png and b/src/assets/images/units/unit-lu-bu-actions.png differ diff --git a/src/assets/images/units/unit-lu-bu.png b/src/assets/images/units/unit-lu-bu.png index ce613e5..48b3483 100644 Binary files a/src/assets/images/units/unit-lu-bu.png and b/src/assets/images/units/unit-lu-bu.png differ diff --git a/src/assets/images/units/unit-lu-meng-actions.png b/src/assets/images/units/unit-lu-meng-actions.png index f6f542e..24d7357 100644 Binary files a/src/assets/images/units/unit-lu-meng-actions.png and b/src/assets/images/units/unit-lu-meng-actions.png differ diff --git a/src/assets/images/units/unit-lu-meng.png b/src/assets/images/units/unit-lu-meng.png index 979c3ef..ecfe46d 100644 Binary files a/src/assets/images/units/unit-lu-meng.png and b/src/assets/images/units/unit-lu-meng.png differ diff --git a/src/assets/images/units/unit-ma-chao-actions.png b/src/assets/images/units/unit-ma-chao-actions.png index a123c82..c20dfa5 100644 Binary files a/src/assets/images/units/unit-ma-chao-actions.png and b/src/assets/images/units/unit-ma-chao-actions.png differ diff --git a/src/assets/images/units/unit-ma-chao.png b/src/assets/images/units/unit-ma-chao.png index 26e55ca..18a9da4 100644 Binary files a/src/assets/images/units/unit-ma-chao.png and b/src/assets/images/units/unit-ma-chao.png differ diff --git a/src/assets/images/units/unit-ma-dai-actions.png b/src/assets/images/units/unit-ma-dai-actions.png index bedd838..e7c040d 100644 Binary files a/src/assets/images/units/unit-ma-dai-actions.png and b/src/assets/images/units/unit-ma-dai-actions.png differ diff --git a/src/assets/images/units/unit-ma-dai.png b/src/assets/images/units/unit-ma-dai.png index 7e950e0..ef082ba 100644 Binary files a/src/assets/images/units/unit-ma-dai.png and b/src/assets/images/units/unit-ma-dai.png differ diff --git a/src/assets/images/units/unit-ma-liang-actions.png b/src/assets/images/units/unit-ma-liang-actions.png index c507241..8691069 100644 Binary files a/src/assets/images/units/unit-ma-liang-actions.png and b/src/assets/images/units/unit-ma-liang-actions.png differ diff --git a/src/assets/images/units/unit-ma-liang.png b/src/assets/images/units/unit-ma-liang.png index cff66ae..f13f59c 100644 Binary files a/src/assets/images/units/unit-ma-liang.png and b/src/assets/images/units/unit-ma-liang.png differ diff --git a/src/assets/images/units/unit-meng-huo-actions.png b/src/assets/images/units/unit-meng-huo-actions.png index 4ae2ece..0606b25 100644 Binary files a/src/assets/images/units/unit-meng-huo-actions.png and b/src/assets/images/units/unit-meng-huo-actions.png differ diff --git a/src/assets/images/units/unit-meng-huo.png b/src/assets/images/units/unit-meng-huo.png index 8f33a7b..a3e70a7 100644 Binary files a/src/assets/images/units/unit-meng-huo.png and b/src/assets/images/units/unit-meng-huo.png differ diff --git a/src/assets/images/units/unit-nanman-infantry-actions.png b/src/assets/images/units/unit-nanman-infantry-actions.png index 4a3d040..b7115e6 100644 Binary files a/src/assets/images/units/unit-nanman-infantry-actions.png and b/src/assets/images/units/unit-nanman-infantry-actions.png differ diff --git a/src/assets/images/units/unit-nanman-infantry-jungle-actions.png b/src/assets/images/units/unit-nanman-infantry-jungle-actions.png index 4a3d040..58f38cc 100644 Binary files a/src/assets/images/units/unit-nanman-infantry-jungle-actions.png and b/src/assets/images/units/unit-nanman-infantry-jungle-actions.png differ diff --git a/src/assets/images/units/unit-nanman-infantry-jungle.png b/src/assets/images/units/unit-nanman-infantry-jungle.png index 10e48f0..0112de5 100644 Binary files a/src/assets/images/units/unit-nanman-infantry-jungle.png and b/src/assets/images/units/unit-nanman-infantry-jungle.png differ diff --git a/src/assets/images/units/unit-nanman-infantry-spear-actions.png b/src/assets/images/units/unit-nanman-infantry-spear-actions.png index 4a3d040..a36223c 100644 Binary files a/src/assets/images/units/unit-nanman-infantry-spear-actions.png and b/src/assets/images/units/unit-nanman-infantry-spear-actions.png differ diff --git a/src/assets/images/units/unit-nanman-infantry-spear.png b/src/assets/images/units/unit-nanman-infantry-spear.png index 10e48f0..7ecdcf3 100644 Binary files a/src/assets/images/units/unit-nanman-infantry-spear.png and b/src/assets/images/units/unit-nanman-infantry-spear.png differ diff --git a/src/assets/images/units/unit-nanman-infantry.png b/src/assets/images/units/unit-nanman-infantry.png index 10e48f0..8f08c55 100644 Binary files a/src/assets/images/units/unit-nanman-infantry.png and b/src/assets/images/units/unit-nanman-infantry.png differ diff --git a/src/assets/images/units/unit-nanman-officer-actions.png b/src/assets/images/units/unit-nanman-officer-actions.png index 30b61af..c12ce54 100644 Binary files a/src/assets/images/units/unit-nanman-officer-actions.png and b/src/assets/images/units/unit-nanman-officer-actions.png differ diff --git a/src/assets/images/units/unit-nanman-officer-bronze-actions.png b/src/assets/images/units/unit-nanman-officer-bronze-actions.png index 30b61af..2644cab 100644 Binary files a/src/assets/images/units/unit-nanman-officer-bronze-actions.png and b/src/assets/images/units/unit-nanman-officer-bronze-actions.png differ diff --git a/src/assets/images/units/unit-nanman-officer-bronze.png b/src/assets/images/units/unit-nanman-officer-bronze.png index 11bdae1..304a44e 100644 Binary files a/src/assets/images/units/unit-nanman-officer-bronze.png and b/src/assets/images/units/unit-nanman-officer-bronze.png differ diff --git a/src/assets/images/units/unit-nanman-officer-warlord-actions.png b/src/assets/images/units/unit-nanman-officer-warlord-actions.png index 30b61af..0e19442 100644 Binary files a/src/assets/images/units/unit-nanman-officer-warlord-actions.png and b/src/assets/images/units/unit-nanman-officer-warlord-actions.png differ diff --git a/src/assets/images/units/unit-nanman-officer-warlord.png b/src/assets/images/units/unit-nanman-officer-warlord.png index 11bdae1..3eb904f 100644 Binary files a/src/assets/images/units/unit-nanman-officer-warlord.png and b/src/assets/images/units/unit-nanman-officer-warlord.png differ diff --git a/src/assets/images/units/unit-nanman-officer.png b/src/assets/images/units/unit-nanman-officer.png index 11bdae1..bda1170 100644 Binary files a/src/assets/images/units/unit-nanman-officer.png and b/src/assets/images/units/unit-nanman-officer.png differ diff --git a/src/assets/images/units/unit-nanman-shaman-actions.png b/src/assets/images/units/unit-nanman-shaman-actions.png index 8aa1570..76ffc16 100644 Binary files a/src/assets/images/units/unit-nanman-shaman-actions.png and b/src/assets/images/units/unit-nanman-shaman-actions.png differ diff --git a/src/assets/images/units/unit-nanman-shaman-ember-actions.png b/src/assets/images/units/unit-nanman-shaman-ember-actions.png index 8aa1570..8924564 100644 Binary files a/src/assets/images/units/unit-nanman-shaman-ember-actions.png and b/src/assets/images/units/unit-nanman-shaman-ember-actions.png differ diff --git a/src/assets/images/units/unit-nanman-shaman-ember.png b/src/assets/images/units/unit-nanman-shaman-ember.png index f4e1d60..86e52d2 100644 Binary files a/src/assets/images/units/unit-nanman-shaman-ember.png and b/src/assets/images/units/unit-nanman-shaman-ember.png differ diff --git a/src/assets/images/units/unit-nanman-shaman-storm-actions.png b/src/assets/images/units/unit-nanman-shaman-storm-actions.png index 8aa1570..10ee8ff 100644 Binary files a/src/assets/images/units/unit-nanman-shaman-storm-actions.png and b/src/assets/images/units/unit-nanman-shaman-storm-actions.png differ diff --git a/src/assets/images/units/unit-nanman-shaman-storm.png b/src/assets/images/units/unit-nanman-shaman-storm.png index f4e1d60..7adc6d5 100644 Binary files a/src/assets/images/units/unit-nanman-shaman-storm.png and b/src/assets/images/units/unit-nanman-shaman-storm.png differ diff --git a/src/assets/images/units/unit-nanman-shaman.png b/src/assets/images/units/unit-nanman-shaman.png index f4e1d60..73bcc9f 100644 Binary files a/src/assets/images/units/unit-nanman-shaman.png and b/src/assets/images/units/unit-nanman-shaman.png differ diff --git a/src/assets/images/units/unit-pang-tong-actions.png b/src/assets/images/units/unit-pang-tong-actions.png index 11ebe13..8996086 100644 Binary files a/src/assets/images/units/unit-pang-tong-actions.png and b/src/assets/images/units/unit-pang-tong-actions.png differ diff --git a/src/assets/images/units/unit-pang-tong.png b/src/assets/images/units/unit-pang-tong.png index 6cec4e8..8560fa6 100644 Binary files a/src/assets/images/units/unit-pang-tong.png and b/src/assets/images/units/unit-pang-tong.png differ diff --git a/src/assets/images/units/unit-rebel-actions.png b/src/assets/images/units/unit-rebel-actions.png index d8af75a..64155fb 100644 Binary files a/src/assets/images/units/unit-rebel-actions.png and b/src/assets/images/units/unit-rebel-actions.png differ diff --git a/src/assets/images/units/unit-rebel-archer-actions.png b/src/assets/images/units/unit-rebel-archer-actions.png index 684971d..df5a9e1 100644 Binary files a/src/assets/images/units/unit-rebel-archer-actions.png and b/src/assets/images/units/unit-rebel-archer-actions.png differ diff --git a/src/assets/images/units/unit-rebel-archer-fire-actions.png b/src/assets/images/units/unit-rebel-archer-fire-actions.png index 165036c..3fa4ba9 100644 Binary files a/src/assets/images/units/unit-rebel-archer-fire-actions.png and b/src/assets/images/units/unit-rebel-archer-fire-actions.png differ diff --git a/src/assets/images/units/unit-rebel-archer-fire.png b/src/assets/images/units/unit-rebel-archer-fire.png index 377fe3e..7db259c 100644 Binary files a/src/assets/images/units/unit-rebel-archer-fire.png and b/src/assets/images/units/unit-rebel-archer-fire.png differ diff --git a/src/assets/images/units/unit-rebel-archer-veteran-actions.png b/src/assets/images/units/unit-rebel-archer-veteran-actions.png index dcb08ac..d26139a 100644 Binary files a/src/assets/images/units/unit-rebel-archer-veteran-actions.png and b/src/assets/images/units/unit-rebel-archer-veteran-actions.png differ diff --git a/src/assets/images/units/unit-rebel-archer-veteran.png b/src/assets/images/units/unit-rebel-archer-veteran.png index a2f4719..03c6770 100644 Binary files a/src/assets/images/units/unit-rebel-archer-veteran.png and b/src/assets/images/units/unit-rebel-archer-veteran.png differ diff --git a/src/assets/images/units/unit-rebel-archer.png b/src/assets/images/units/unit-rebel-archer.png index 70dd566..7c044a0 100644 Binary files a/src/assets/images/units/unit-rebel-archer.png and b/src/assets/images/units/unit-rebel-archer.png differ diff --git a/src/assets/images/units/unit-rebel-cavalry-actions.png b/src/assets/images/units/unit-rebel-cavalry-actions.png index 14a81e4..d746632 100644 Binary files a/src/assets/images/units/unit-rebel-cavalry-actions.png and b/src/assets/images/units/unit-rebel-cavalry-actions.png differ diff --git a/src/assets/images/units/unit-rebel-cavalry-veteran-actions.png b/src/assets/images/units/unit-rebel-cavalry-veteran-actions.png index a6d6d08..59f8984 100644 Binary files a/src/assets/images/units/unit-rebel-cavalry-veteran-actions.png and b/src/assets/images/units/unit-rebel-cavalry-veteran-actions.png differ diff --git a/src/assets/images/units/unit-rebel-cavalry-veteran.png b/src/assets/images/units/unit-rebel-cavalry-veteran.png index 2cbbd41..ec0aba6 100644 Binary files a/src/assets/images/units/unit-rebel-cavalry-veteran.png and b/src/assets/images/units/unit-rebel-cavalry-veteran.png differ diff --git a/src/assets/images/units/unit-rebel-cavalry.png b/src/assets/images/units/unit-rebel-cavalry.png index e30e207..317415f 100644 Binary files a/src/assets/images/units/unit-rebel-cavalry.png and b/src/assets/images/units/unit-rebel-cavalry.png differ diff --git a/src/assets/images/units/unit-rebel-leader-actions.png b/src/assets/images/units/unit-rebel-leader-actions.png index c600448..a766ccb 100644 Binary files a/src/assets/images/units/unit-rebel-leader-actions.png and b/src/assets/images/units/unit-rebel-leader-actions.png differ diff --git a/src/assets/images/units/unit-rebel-leader-warlord-actions.png b/src/assets/images/units/unit-rebel-leader-warlord-actions.png index 1311503..67ba63f 100644 Binary files a/src/assets/images/units/unit-rebel-leader-warlord-actions.png and b/src/assets/images/units/unit-rebel-leader-warlord-actions.png differ diff --git a/src/assets/images/units/unit-rebel-leader-warlord.png b/src/assets/images/units/unit-rebel-leader-warlord.png index 058fade..6514a15 100644 Binary files a/src/assets/images/units/unit-rebel-leader-warlord.png and b/src/assets/images/units/unit-rebel-leader-warlord.png differ diff --git a/src/assets/images/units/unit-rebel-leader.png b/src/assets/images/units/unit-rebel-leader.png index 2a49031..1843ab6 100644 Binary files a/src/assets/images/units/unit-rebel-leader.png and b/src/assets/images/units/unit-rebel-leader.png differ diff --git a/src/assets/images/units/unit-rebel-ragged-actions.png b/src/assets/images/units/unit-rebel-ragged-actions.png index 51ecb24..d5ec782 100644 Binary files a/src/assets/images/units/unit-rebel-ragged-actions.png and b/src/assets/images/units/unit-rebel-ragged-actions.png differ diff --git a/src/assets/images/units/unit-rebel-ragged.png b/src/assets/images/units/unit-rebel-ragged.png index 0931d64..94affc9 100644 Binary files a/src/assets/images/units/unit-rebel-ragged.png and b/src/assets/images/units/unit-rebel-ragged.png differ diff --git a/src/assets/images/units/unit-rebel.png b/src/assets/images/units/unit-rebel.png index 8a83f09..8c52538 100644 Binary files a/src/assets/images/units/unit-rebel.png and b/src/assets/images/units/unit-rebel.png differ diff --git a/src/assets/images/units/unit-shu-archer-actions.png b/src/assets/images/units/unit-shu-archer-actions.png index 6cb17d8..a092eb6 100644 Binary files a/src/assets/images/units/unit-shu-archer-actions.png and b/src/assets/images/units/unit-shu-archer-actions.png differ diff --git a/src/assets/images/units/unit-shu-archer-longbow-actions.png b/src/assets/images/units/unit-shu-archer-longbow-actions.png index 6cb17d8..5c46cc1 100644 Binary files a/src/assets/images/units/unit-shu-archer-longbow-actions.png and b/src/assets/images/units/unit-shu-archer-longbow-actions.png differ diff --git a/src/assets/images/units/unit-shu-archer-longbow.png b/src/assets/images/units/unit-shu-archer-longbow.png index 0974883..4ac8998 100644 Binary files a/src/assets/images/units/unit-shu-archer-longbow.png and b/src/assets/images/units/unit-shu-archer-longbow.png differ diff --git a/src/assets/images/units/unit-shu-archer-veteran-actions.png b/src/assets/images/units/unit-shu-archer-veteran-actions.png index 6cb17d8..d2e9ee3 100644 Binary files a/src/assets/images/units/unit-shu-archer-veteran-actions.png and b/src/assets/images/units/unit-shu-archer-veteran-actions.png differ diff --git a/src/assets/images/units/unit-shu-archer-veteran.png b/src/assets/images/units/unit-shu-archer-veteran.png index 0974883..8e551ea 100644 Binary files a/src/assets/images/units/unit-shu-archer-veteran.png and b/src/assets/images/units/unit-shu-archer-veteran.png differ diff --git a/src/assets/images/units/unit-shu-archer.png b/src/assets/images/units/unit-shu-archer.png index 0974883..4fb5ed5 100644 Binary files a/src/assets/images/units/unit-shu-archer.png and b/src/assets/images/units/unit-shu-archer.png differ diff --git a/src/assets/images/units/unit-shu-cavalry-actions.png b/src/assets/images/units/unit-shu-cavalry-actions.png index dde4f61..41698a0 100644 Binary files a/src/assets/images/units/unit-shu-cavalry-actions.png and b/src/assets/images/units/unit-shu-cavalry-actions.png differ diff --git a/src/assets/images/units/unit-shu-cavalry-scout-actions.png b/src/assets/images/units/unit-shu-cavalry-scout-actions.png index dde4f61..5549b64 100644 Binary files a/src/assets/images/units/unit-shu-cavalry-scout-actions.png and b/src/assets/images/units/unit-shu-cavalry-scout-actions.png differ diff --git a/src/assets/images/units/unit-shu-cavalry-scout.png b/src/assets/images/units/unit-shu-cavalry-scout.png index 87eacdf..0096a3a 100644 Binary files a/src/assets/images/units/unit-shu-cavalry-scout.png and b/src/assets/images/units/unit-shu-cavalry-scout.png differ diff --git a/src/assets/images/units/unit-shu-cavalry-white-actions.png b/src/assets/images/units/unit-shu-cavalry-white-actions.png index dde4f61..bc3bed3 100644 Binary files a/src/assets/images/units/unit-shu-cavalry-white-actions.png and b/src/assets/images/units/unit-shu-cavalry-white-actions.png differ diff --git a/src/assets/images/units/unit-shu-cavalry-white.png b/src/assets/images/units/unit-shu-cavalry-white.png index 87eacdf..f312463 100644 Binary files a/src/assets/images/units/unit-shu-cavalry-white.png and b/src/assets/images/units/unit-shu-cavalry-white.png differ diff --git a/src/assets/images/units/unit-shu-cavalry.png b/src/assets/images/units/unit-shu-cavalry.png index 87eacdf..86dda02 100644 Binary files a/src/assets/images/units/unit-shu-cavalry.png and b/src/assets/images/units/unit-shu-cavalry.png differ diff --git a/src/assets/images/units/unit-shu-infantry-actions.png b/src/assets/images/units/unit-shu-infantry-actions.png index dd6f9f2..6be95fd 100644 Binary files a/src/assets/images/units/unit-shu-infantry-actions.png and b/src/assets/images/units/unit-shu-infantry-actions.png differ diff --git a/src/assets/images/units/unit-shu-infantry-banner-actions.png b/src/assets/images/units/unit-shu-infantry-banner-actions.png index dd6f9f2..c1ffe64 100644 Binary files a/src/assets/images/units/unit-shu-infantry-banner-actions.png and b/src/assets/images/units/unit-shu-infantry-banner-actions.png differ diff --git a/src/assets/images/units/unit-shu-infantry-banner.png b/src/assets/images/units/unit-shu-infantry-banner.png index c028d31..a705e5d 100644 Binary files a/src/assets/images/units/unit-shu-infantry-banner.png and b/src/assets/images/units/unit-shu-infantry-banner.png differ diff --git a/src/assets/images/units/unit-shu-infantry-guard-actions.png b/src/assets/images/units/unit-shu-infantry-guard-actions.png index dd6f9f2..c99bbe6 100644 Binary files a/src/assets/images/units/unit-shu-infantry-guard-actions.png and b/src/assets/images/units/unit-shu-infantry-guard-actions.png differ diff --git a/src/assets/images/units/unit-shu-infantry-guard.png b/src/assets/images/units/unit-shu-infantry-guard.png index c028d31..db7fe5c 100644 Binary files a/src/assets/images/units/unit-shu-infantry-guard.png and b/src/assets/images/units/unit-shu-infantry-guard.png differ diff --git a/src/assets/images/units/unit-shu-infantry.png b/src/assets/images/units/unit-shu-infantry.png index c028d31..37c009b 100644 Binary files a/src/assets/images/units/unit-shu-infantry.png and b/src/assets/images/units/unit-shu-infantry.png differ diff --git a/src/assets/images/units/unit-shu-officer-actions.png b/src/assets/images/units/unit-shu-officer-actions.png index 7634f57..9015fdb 100644 Binary files a/src/assets/images/units/unit-shu-officer-actions.png and b/src/assets/images/units/unit-shu-officer-actions.png differ diff --git a/src/assets/images/units/unit-shu-officer-council-actions.png b/src/assets/images/units/unit-shu-officer-council-actions.png index 7634f57..90a9288 100644 Binary files a/src/assets/images/units/unit-shu-officer-council-actions.png and b/src/assets/images/units/unit-shu-officer-council-actions.png differ diff --git a/src/assets/images/units/unit-shu-officer-council.png b/src/assets/images/units/unit-shu-officer-council.png index 08f5632..3f96672 100644 Binary files a/src/assets/images/units/unit-shu-officer-council.png and b/src/assets/images/units/unit-shu-officer-council.png differ diff --git a/src/assets/images/units/unit-shu-officer-vanguard-actions.png b/src/assets/images/units/unit-shu-officer-vanguard-actions.png index 7634f57..e6ab3b8 100644 Binary files a/src/assets/images/units/unit-shu-officer-vanguard-actions.png and b/src/assets/images/units/unit-shu-officer-vanguard-actions.png differ diff --git a/src/assets/images/units/unit-shu-officer-vanguard.png b/src/assets/images/units/unit-shu-officer-vanguard.png index 08f5632..f6eb62e 100644 Binary files a/src/assets/images/units/unit-shu-officer-vanguard.png and b/src/assets/images/units/unit-shu-officer-vanguard.png differ diff --git a/src/assets/images/units/unit-shu-officer.png b/src/assets/images/units/unit-shu-officer.png index 08f5632..ecd2885 100644 Binary files a/src/assets/images/units/unit-shu-officer.png and b/src/assets/images/units/unit-shu-officer.png differ diff --git a/src/assets/images/units/unit-shu-spearman-actions.png b/src/assets/images/units/unit-shu-spearman-actions.png index ab244a6..0a84eeb 100644 Binary files a/src/assets/images/units/unit-shu-spearman-actions.png and b/src/assets/images/units/unit-shu-spearman-actions.png differ diff --git a/src/assets/images/units/unit-shu-spearman-guard-actions.png b/src/assets/images/units/unit-shu-spearman-guard-actions.png index ab244a6..5ede85b 100644 Binary files a/src/assets/images/units/unit-shu-spearman-guard-actions.png and b/src/assets/images/units/unit-shu-spearman-guard-actions.png differ diff --git a/src/assets/images/units/unit-shu-spearman-guard.png b/src/assets/images/units/unit-shu-spearman-guard.png index ce0bc9e..862e0c0 100644 Binary files a/src/assets/images/units/unit-shu-spearman-guard.png and b/src/assets/images/units/unit-shu-spearman-guard.png differ diff --git a/src/assets/images/units/unit-shu-spearman-veteran-actions.png b/src/assets/images/units/unit-shu-spearman-veteran-actions.png index ab244a6..ea5f5b4 100644 Binary files a/src/assets/images/units/unit-shu-spearman-veteran-actions.png and b/src/assets/images/units/unit-shu-spearman-veteran-actions.png differ diff --git a/src/assets/images/units/unit-shu-spearman-veteran.png b/src/assets/images/units/unit-shu-spearman-veteran.png index ce0bc9e..528bdb9 100644 Binary files a/src/assets/images/units/unit-shu-spearman-veteran.png and b/src/assets/images/units/unit-shu-spearman-veteran.png differ diff --git a/src/assets/images/units/unit-shu-spearman.png b/src/assets/images/units/unit-shu-spearman.png index ce0bc9e..b6031de 100644 Binary files a/src/assets/images/units/unit-shu-spearman.png and b/src/assets/images/units/unit-shu-spearman.png differ diff --git a/src/assets/images/units/unit-shu-strategist-actions.png b/src/assets/images/units/unit-shu-strategist-actions.png index c849dbf..8691069 100644 Binary files a/src/assets/images/units/unit-shu-strategist-actions.png and b/src/assets/images/units/unit-shu-strategist-actions.png differ diff --git a/src/assets/images/units/unit-shu-strategist-field-actions.png b/src/assets/images/units/unit-shu-strategist-field-actions.png index c849dbf..7d0d8d5 100644 Binary files a/src/assets/images/units/unit-shu-strategist-field-actions.png and b/src/assets/images/units/unit-shu-strategist-field-actions.png differ diff --git a/src/assets/images/units/unit-shu-strategist-field.png b/src/assets/images/units/unit-shu-strategist-field.png index 35fe4fc..1a1cc72 100644 Binary files a/src/assets/images/units/unit-shu-strategist-field.png and b/src/assets/images/units/unit-shu-strategist-field.png differ diff --git a/src/assets/images/units/unit-shu-strategist-white-actions.png b/src/assets/images/units/unit-shu-strategist-white-actions.png index c849dbf..f7b1d16 100644 Binary files a/src/assets/images/units/unit-shu-strategist-white-actions.png and b/src/assets/images/units/unit-shu-strategist-white-actions.png differ diff --git a/src/assets/images/units/unit-shu-strategist-white.png b/src/assets/images/units/unit-shu-strategist-white.png index 35fe4fc..e7042e2 100644 Binary files a/src/assets/images/units/unit-shu-strategist-white.png and b/src/assets/images/units/unit-shu-strategist-white.png differ diff --git a/src/assets/images/units/unit-shu-strategist.png b/src/assets/images/units/unit-shu-strategist.png index 35fe4fc..f13f59c 100644 Binary files a/src/assets/images/units/unit-shu-strategist.png and b/src/assets/images/units/unit-shu-strategist.png differ diff --git a/src/assets/images/units/unit-sima-yi-actions.png b/src/assets/images/units/unit-sima-yi-actions.png index dd7e8d5..56c98b0 100644 Binary files a/src/assets/images/units/unit-sima-yi-actions.png and b/src/assets/images/units/unit-sima-yi-actions.png differ diff --git a/src/assets/images/units/unit-sima-yi.png b/src/assets/images/units/unit-sima-yi.png index ebebdc9..528286b 100644 Binary files a/src/assets/images/units/unit-sima-yi.png and b/src/assets/images/units/unit-sima-yi.png differ diff --git a/src/assets/images/units/unit-wang-ping-actions.png b/src/assets/images/units/unit-wang-ping-actions.png index 16fd14d..3ffb12d 100644 Binary files a/src/assets/images/units/unit-wang-ping-actions.png and b/src/assets/images/units/unit-wang-ping-actions.png differ diff --git a/src/assets/images/units/unit-wang-ping.png b/src/assets/images/units/unit-wang-ping.png index f8d7ffc..ad4a1b4 100644 Binary files a/src/assets/images/units/unit-wang-ping.png and b/src/assets/images/units/unit-wang-ping.png differ diff --git a/src/assets/images/units/unit-wei-archer-actions.png b/src/assets/images/units/unit-wei-archer-actions.png index 3921113..b09bce9 100644 Binary files a/src/assets/images/units/unit-wei-archer-actions.png and b/src/assets/images/units/unit-wei-archer-actions.png differ diff --git a/src/assets/images/units/unit-wei-archer-crossbow-actions.png b/src/assets/images/units/unit-wei-archer-crossbow-actions.png index 3921113..83fac09 100644 Binary files a/src/assets/images/units/unit-wei-archer-crossbow-actions.png and b/src/assets/images/units/unit-wei-archer-crossbow-actions.png differ diff --git a/src/assets/images/units/unit-wei-archer-crossbow.png b/src/assets/images/units/unit-wei-archer-crossbow.png index 4d52261..fa61043 100644 Binary files a/src/assets/images/units/unit-wei-archer-crossbow.png and b/src/assets/images/units/unit-wei-archer-crossbow.png differ diff --git a/src/assets/images/units/unit-wei-archer-veteran-actions.png b/src/assets/images/units/unit-wei-archer-veteran-actions.png index 3921113..71756b6 100644 Binary files a/src/assets/images/units/unit-wei-archer-veteran-actions.png and b/src/assets/images/units/unit-wei-archer-veteran-actions.png differ diff --git a/src/assets/images/units/unit-wei-archer-veteran.png b/src/assets/images/units/unit-wei-archer-veteran.png index 4d52261..1455b3d 100644 Binary files a/src/assets/images/units/unit-wei-archer-veteran.png and b/src/assets/images/units/unit-wei-archer-veteran.png differ diff --git a/src/assets/images/units/unit-wei-archer.png b/src/assets/images/units/unit-wei-archer.png index 4d52261..40d5d86 100644 Binary files a/src/assets/images/units/unit-wei-archer.png and b/src/assets/images/units/unit-wei-archer.png differ diff --git a/src/assets/images/units/unit-wei-cavalry-actions.png b/src/assets/images/units/unit-wei-cavalry-actions.png index b11645b..e6de620 100644 Binary files a/src/assets/images/units/unit-wei-cavalry-actions.png and b/src/assets/images/units/unit-wei-cavalry-actions.png differ diff --git a/src/assets/images/units/unit-wei-cavalry-elite-actions.png b/src/assets/images/units/unit-wei-cavalry-elite-actions.png index b11645b..c1313b7 100644 Binary files a/src/assets/images/units/unit-wei-cavalry-elite-actions.png and b/src/assets/images/units/unit-wei-cavalry-elite-actions.png differ diff --git a/src/assets/images/units/unit-wei-cavalry-elite.png b/src/assets/images/units/unit-wei-cavalry-elite.png index c9cf168..51cd677 100644 Binary files a/src/assets/images/units/unit-wei-cavalry-elite.png and b/src/assets/images/units/unit-wei-cavalry-elite.png differ diff --git a/src/assets/images/units/unit-wei-cavalry-iron-actions.png b/src/assets/images/units/unit-wei-cavalry-iron-actions.png index b11645b..5c79740 100644 Binary files a/src/assets/images/units/unit-wei-cavalry-iron-actions.png and b/src/assets/images/units/unit-wei-cavalry-iron-actions.png differ diff --git a/src/assets/images/units/unit-wei-cavalry-iron.png b/src/assets/images/units/unit-wei-cavalry-iron.png index c9cf168..b1f370c 100644 Binary files a/src/assets/images/units/unit-wei-cavalry-iron.png and b/src/assets/images/units/unit-wei-cavalry-iron.png differ diff --git a/src/assets/images/units/unit-wei-cavalry.png b/src/assets/images/units/unit-wei-cavalry.png index c9cf168..889a89c 100644 Binary files a/src/assets/images/units/unit-wei-cavalry.png and b/src/assets/images/units/unit-wei-cavalry.png differ diff --git a/src/assets/images/units/unit-wei-infantry-actions.png b/src/assets/images/units/unit-wei-infantry-actions.png index d21f212..a5e81b0 100644 Binary files a/src/assets/images/units/unit-wei-infantry-actions.png and b/src/assets/images/units/unit-wei-infantry-actions.png differ diff --git a/src/assets/images/units/unit-wei-infantry-shield-actions.png b/src/assets/images/units/unit-wei-infantry-shield-actions.png index d21f212..518ee89 100644 Binary files a/src/assets/images/units/unit-wei-infantry-shield-actions.png and b/src/assets/images/units/unit-wei-infantry-shield-actions.png differ diff --git a/src/assets/images/units/unit-wei-infantry-shield.png b/src/assets/images/units/unit-wei-infantry-shield.png index 82fdf1b..86251a5 100644 Binary files a/src/assets/images/units/unit-wei-infantry-shield.png and b/src/assets/images/units/unit-wei-infantry-shield.png differ diff --git a/src/assets/images/units/unit-wei-infantry-veteran-actions.png b/src/assets/images/units/unit-wei-infantry-veteran-actions.png index d21f212..77d392e 100644 Binary files a/src/assets/images/units/unit-wei-infantry-veteran-actions.png and b/src/assets/images/units/unit-wei-infantry-veteran-actions.png differ diff --git a/src/assets/images/units/unit-wei-infantry-veteran.png b/src/assets/images/units/unit-wei-infantry-veteran.png index 82fdf1b..e2171cd 100644 Binary files a/src/assets/images/units/unit-wei-infantry-veteran.png and b/src/assets/images/units/unit-wei-infantry-veteran.png differ diff --git a/src/assets/images/units/unit-wei-infantry.png b/src/assets/images/units/unit-wei-infantry.png index 82fdf1b..aaa8595 100644 Binary files a/src/assets/images/units/unit-wei-infantry.png and b/src/assets/images/units/unit-wei-infantry.png differ diff --git a/src/assets/images/units/unit-wei-officer-actions.png b/src/assets/images/units/unit-wei-officer-actions.png index 88b941e..9d22d95 100644 Binary files a/src/assets/images/units/unit-wei-officer-actions.png and b/src/assets/images/units/unit-wei-officer-actions.png differ diff --git a/src/assets/images/units/unit-wei-officer-gate-actions.png b/src/assets/images/units/unit-wei-officer-gate-actions.png index 88b941e..1668ca7 100644 Binary files a/src/assets/images/units/unit-wei-officer-gate-actions.png and b/src/assets/images/units/unit-wei-officer-gate-actions.png differ diff --git a/src/assets/images/units/unit-wei-officer-gate.png b/src/assets/images/units/unit-wei-officer-gate.png index 9adb78f..aeaaa20 100644 Binary files a/src/assets/images/units/unit-wei-officer-gate.png and b/src/assets/images/units/unit-wei-officer-gate.png differ diff --git a/src/assets/images/units/unit-wei-officer-iron-actions.png b/src/assets/images/units/unit-wei-officer-iron-actions.png index 88b941e..2c64d62 100644 Binary files a/src/assets/images/units/unit-wei-officer-iron-actions.png and b/src/assets/images/units/unit-wei-officer-iron-actions.png differ diff --git a/src/assets/images/units/unit-wei-officer-iron.png b/src/assets/images/units/unit-wei-officer-iron.png index 9adb78f..a79d891 100644 Binary files a/src/assets/images/units/unit-wei-officer-iron.png and b/src/assets/images/units/unit-wei-officer-iron.png differ diff --git a/src/assets/images/units/unit-wei-officer.png b/src/assets/images/units/unit-wei-officer.png index 9adb78f..31675ce 100644 Binary files a/src/assets/images/units/unit-wei-officer.png and b/src/assets/images/units/unit-wei-officer.png differ diff --git a/src/assets/images/units/unit-wei-strategist-actions.png b/src/assets/images/units/unit-wei-strategist-actions.png index 2066141..d1b53c3 100644 Binary files a/src/assets/images/units/unit-wei-strategist-actions.png and b/src/assets/images/units/unit-wei-strategist-actions.png differ diff --git a/src/assets/images/units/unit-wei-strategist-black-actions.png b/src/assets/images/units/unit-wei-strategist-black-actions.png index 2066141..3feea09 100644 Binary files a/src/assets/images/units/unit-wei-strategist-black-actions.png and b/src/assets/images/units/unit-wei-strategist-black-actions.png differ diff --git a/src/assets/images/units/unit-wei-strategist-black.png b/src/assets/images/units/unit-wei-strategist-black.png index 41ece7b..004a1ab 100644 Binary files a/src/assets/images/units/unit-wei-strategist-black.png and b/src/assets/images/units/unit-wei-strategist-black.png differ diff --git a/src/assets/images/units/unit-wei-strategist-blue-actions.png b/src/assets/images/units/unit-wei-strategist-blue-actions.png index 2066141..c9ca64a 100644 Binary files a/src/assets/images/units/unit-wei-strategist-blue-actions.png and b/src/assets/images/units/unit-wei-strategist-blue-actions.png differ diff --git a/src/assets/images/units/unit-wei-strategist-blue.png b/src/assets/images/units/unit-wei-strategist-blue.png index 41ece7b..e10a5e3 100644 Binary files a/src/assets/images/units/unit-wei-strategist-blue.png and b/src/assets/images/units/unit-wei-strategist-blue.png differ diff --git a/src/assets/images/units/unit-wei-strategist.png b/src/assets/images/units/unit-wei-strategist.png index 41ece7b..3d3ba2a 100644 Binary files a/src/assets/images/units/unit-wei-strategist.png and b/src/assets/images/units/unit-wei-strategist.png differ diff --git a/src/assets/images/units/unit-wei-yan-actions.png b/src/assets/images/units/unit-wei-yan-actions.png index 1fd1485..c4c76f1 100644 Binary files a/src/assets/images/units/unit-wei-yan-actions.png and b/src/assets/images/units/unit-wei-yan-actions.png differ diff --git a/src/assets/images/units/unit-wei-yan.png b/src/assets/images/units/unit-wei-yan.png index af26586..1278d79 100644 Binary files a/src/assets/images/units/unit-wei-yan.png and b/src/assets/images/units/unit-wei-yan.png differ diff --git a/src/assets/images/units/unit-wu-archer-actions.png b/src/assets/images/units/unit-wu-archer-actions.png index 2338872..ff3e854 100644 Binary files a/src/assets/images/units/unit-wu-archer-actions.png and b/src/assets/images/units/unit-wu-archer-actions.png differ diff --git a/src/assets/images/units/unit-wu-archer-naval-actions.png b/src/assets/images/units/unit-wu-archer-naval-actions.png index 2338872..ea7593c 100644 Binary files a/src/assets/images/units/unit-wu-archer-naval-actions.png and b/src/assets/images/units/unit-wu-archer-naval-actions.png differ diff --git a/src/assets/images/units/unit-wu-archer-naval.png b/src/assets/images/units/unit-wu-archer-naval.png index 43e414d..a3ff9f0 100644 Binary files a/src/assets/images/units/unit-wu-archer-naval.png and b/src/assets/images/units/unit-wu-archer-naval.png differ diff --git a/src/assets/images/units/unit-wu-archer-river-actions.png b/src/assets/images/units/unit-wu-archer-river-actions.png index 2338872..44d16aa 100644 Binary files a/src/assets/images/units/unit-wu-archer-river-actions.png and b/src/assets/images/units/unit-wu-archer-river-actions.png differ diff --git a/src/assets/images/units/unit-wu-archer-river.png b/src/assets/images/units/unit-wu-archer-river.png index 43e414d..1ae89f5 100644 Binary files a/src/assets/images/units/unit-wu-archer-river.png and b/src/assets/images/units/unit-wu-archer-river.png differ diff --git a/src/assets/images/units/unit-wu-archer.png b/src/assets/images/units/unit-wu-archer.png index 43e414d..c2e98c6 100644 Binary files a/src/assets/images/units/unit-wu-archer.png and b/src/assets/images/units/unit-wu-archer.png differ diff --git a/src/assets/images/units/unit-wu-cavalry-actions.png b/src/assets/images/units/unit-wu-cavalry-actions.png index cfb683b..3092939 100644 Binary files a/src/assets/images/units/unit-wu-cavalry-actions.png and b/src/assets/images/units/unit-wu-cavalry-actions.png differ diff --git a/src/assets/images/units/unit-wu-cavalry-elite-actions.png b/src/assets/images/units/unit-wu-cavalry-elite-actions.png index cfb683b..0ab2c22 100644 Binary files a/src/assets/images/units/unit-wu-cavalry-elite-actions.png and b/src/assets/images/units/unit-wu-cavalry-elite-actions.png differ diff --git a/src/assets/images/units/unit-wu-cavalry-elite.png b/src/assets/images/units/unit-wu-cavalry-elite.png index 8f88e53..400eca0 100644 Binary files a/src/assets/images/units/unit-wu-cavalry-elite.png and b/src/assets/images/units/unit-wu-cavalry-elite.png differ diff --git a/src/assets/images/units/unit-wu-cavalry-river-actions.png b/src/assets/images/units/unit-wu-cavalry-river-actions.png index cfb683b..b3f8f0b 100644 Binary files a/src/assets/images/units/unit-wu-cavalry-river-actions.png and b/src/assets/images/units/unit-wu-cavalry-river-actions.png differ diff --git a/src/assets/images/units/unit-wu-cavalry-river.png b/src/assets/images/units/unit-wu-cavalry-river.png index 8f88e53..8d3a716 100644 Binary files a/src/assets/images/units/unit-wu-cavalry-river.png and b/src/assets/images/units/unit-wu-cavalry-river.png differ diff --git a/src/assets/images/units/unit-wu-cavalry.png b/src/assets/images/units/unit-wu-cavalry.png index 8f88e53..ff58b3d 100644 Binary files a/src/assets/images/units/unit-wu-cavalry.png and b/src/assets/images/units/unit-wu-cavalry.png differ diff --git a/src/assets/images/units/unit-wu-infantry-actions.png b/src/assets/images/units/unit-wu-infantry-actions.png index f179279..03a2251 100644 Binary files a/src/assets/images/units/unit-wu-infantry-actions.png and b/src/assets/images/units/unit-wu-infantry-actions.png differ diff --git a/src/assets/images/units/unit-wu-infantry-marine-actions.png b/src/assets/images/units/unit-wu-infantry-marine-actions.png index f179279..d1bd0fc 100644 Binary files a/src/assets/images/units/unit-wu-infantry-marine-actions.png and b/src/assets/images/units/unit-wu-infantry-marine-actions.png differ diff --git a/src/assets/images/units/unit-wu-infantry-marine.png b/src/assets/images/units/unit-wu-infantry-marine.png index d472ca2..8cd5e62 100644 Binary files a/src/assets/images/units/unit-wu-infantry-marine.png and b/src/assets/images/units/unit-wu-infantry-marine.png differ diff --git a/src/assets/images/units/unit-wu-infantry-river-actions.png b/src/assets/images/units/unit-wu-infantry-river-actions.png index f179279..ee8bb7d 100644 Binary files a/src/assets/images/units/unit-wu-infantry-river-actions.png and b/src/assets/images/units/unit-wu-infantry-river-actions.png differ diff --git a/src/assets/images/units/unit-wu-infantry-river.png b/src/assets/images/units/unit-wu-infantry-river.png index d472ca2..be5a0d8 100644 Binary files a/src/assets/images/units/unit-wu-infantry-river.png and b/src/assets/images/units/unit-wu-infantry-river.png differ diff --git a/src/assets/images/units/unit-wu-infantry.png b/src/assets/images/units/unit-wu-infantry.png index d472ca2..1e96b16 100644 Binary files a/src/assets/images/units/unit-wu-infantry.png and b/src/assets/images/units/unit-wu-infantry.png differ diff --git a/src/assets/images/units/unit-wu-officer-actions.png b/src/assets/images/units/unit-wu-officer-actions.png index 4eb8859..24d7357 100644 Binary files a/src/assets/images/units/unit-wu-officer-actions.png and b/src/assets/images/units/unit-wu-officer-actions.png differ diff --git a/src/assets/images/units/unit-wu-officer-harbor-actions.png b/src/assets/images/units/unit-wu-officer-harbor-actions.png index 4eb8859..e185a79 100644 Binary files a/src/assets/images/units/unit-wu-officer-harbor-actions.png and b/src/assets/images/units/unit-wu-officer-harbor-actions.png differ diff --git a/src/assets/images/units/unit-wu-officer-harbor.png b/src/assets/images/units/unit-wu-officer-harbor.png index 070f9d7..bdc5a56 100644 Binary files a/src/assets/images/units/unit-wu-officer-harbor.png and b/src/assets/images/units/unit-wu-officer-harbor.png differ diff --git a/src/assets/images/units/unit-wu-officer-river-actions.png b/src/assets/images/units/unit-wu-officer-river-actions.png index 4eb8859..24d7357 100644 Binary files a/src/assets/images/units/unit-wu-officer-river-actions.png and b/src/assets/images/units/unit-wu-officer-river-actions.png differ diff --git a/src/assets/images/units/unit-wu-officer-river.png b/src/assets/images/units/unit-wu-officer-river.png index 070f9d7..ecfe46d 100644 Binary files a/src/assets/images/units/unit-wu-officer-river.png and b/src/assets/images/units/unit-wu-officer-river.png differ diff --git a/src/assets/images/units/unit-wu-officer.png b/src/assets/images/units/unit-wu-officer.png index 070f9d7..ecfe46d 100644 Binary files a/src/assets/images/units/unit-wu-officer.png and b/src/assets/images/units/unit-wu-officer.png differ diff --git a/src/assets/images/units/unit-wu-strategist-actions.png b/src/assets/images/units/unit-wu-strategist-actions.png index 84521b6..a22cb97 100644 Binary files a/src/assets/images/units/unit-wu-strategist-actions.png and b/src/assets/images/units/unit-wu-strategist-actions.png differ diff --git a/src/assets/images/units/unit-wu-strategist-fire-actions.png b/src/assets/images/units/unit-wu-strategist-fire-actions.png index 84521b6..eaf8c97 100644 Binary files a/src/assets/images/units/unit-wu-strategist-fire-actions.png and b/src/assets/images/units/unit-wu-strategist-fire-actions.png differ diff --git a/src/assets/images/units/unit-wu-strategist-fire.png b/src/assets/images/units/unit-wu-strategist-fire.png index 467b976..385ec8c 100644 Binary files a/src/assets/images/units/unit-wu-strategist-fire.png and b/src/assets/images/units/unit-wu-strategist-fire.png differ diff --git a/src/assets/images/units/unit-wu-strategist-river-actions.png b/src/assets/images/units/unit-wu-strategist-river-actions.png index 84521b6..0e55060 100644 Binary files a/src/assets/images/units/unit-wu-strategist-river-actions.png and b/src/assets/images/units/unit-wu-strategist-river-actions.png differ diff --git a/src/assets/images/units/unit-wu-strategist-river.png b/src/assets/images/units/unit-wu-strategist-river.png index 467b976..841ee30 100644 Binary files a/src/assets/images/units/unit-wu-strategist-river.png and b/src/assets/images/units/unit-wu-strategist-river.png differ diff --git a/src/assets/images/units/unit-wu-strategist.png b/src/assets/images/units/unit-wu-strategist.png index 467b976..0a02038 100644 Binary files a/src/assets/images/units/unit-wu-strategist.png and b/src/assets/images/units/unit-wu-strategist.png differ diff --git a/src/assets/images/units/unit-wu-yi-actions.png b/src/assets/images/units/unit-wu-yi-actions.png index b46bc4e..c71be69 100644 Binary files a/src/assets/images/units/unit-wu-yi-actions.png and b/src/assets/images/units/unit-wu-yi-actions.png differ diff --git a/src/assets/images/units/unit-wu-yi.png b/src/assets/images/units/unit-wu-yi.png index ce1068b..d42f1b6 100644 Binary files a/src/assets/images/units/unit-wu-yi.png and b/src/assets/images/units/unit-wu-yi.png differ diff --git a/src/assets/images/units/unit-yan-yan-actions.png b/src/assets/images/units/unit-yan-yan-actions.png index 0205cd0..3c2ff22 100644 Binary files a/src/assets/images/units/unit-yan-yan-actions.png and b/src/assets/images/units/unit-yan-yan-actions.png differ diff --git a/src/assets/images/units/unit-yan-yan.png b/src/assets/images/units/unit-yan-yan.png index 892c56b..0089dbe 100644 Binary files a/src/assets/images/units/unit-yan-yan.png and b/src/assets/images/units/unit-yan-yan.png differ diff --git a/src/assets/images/units/unit-yi-ji-actions.png b/src/assets/images/units/unit-yi-ji-actions.png index aa89a2d..ce55bbb 100644 Binary files a/src/assets/images/units/unit-yi-ji-actions.png and b/src/assets/images/units/unit-yi-ji-actions.png differ diff --git a/src/assets/images/units/unit-yi-ji.png b/src/assets/images/units/unit-yi-ji.png index c223705..488fef1 100644 Binary files a/src/assets/images/units/unit-yi-ji.png and b/src/assets/images/units/unit-yi-ji.png differ diff --git a/src/assets/images/units/unit-zhang-fei-actions.png b/src/assets/images/units/unit-zhang-fei-actions.png index 1be2847..886e43a 100644 Binary files a/src/assets/images/units/unit-zhang-fei-actions.png and b/src/assets/images/units/unit-zhang-fei-actions.png differ diff --git a/src/assets/images/units/unit-zhang-fei.png b/src/assets/images/units/unit-zhang-fei.png index 8aaedb0..5b1db84 100644 Binary files a/src/assets/images/units/unit-zhang-fei.png and b/src/assets/images/units/unit-zhang-fei.png differ diff --git a/src/assets/images/units/unit-zhao-yun-actions.png b/src/assets/images/units/unit-zhao-yun-actions.png index da2fca2..c3adc4c 100644 Binary files a/src/assets/images/units/unit-zhao-yun-actions.png and b/src/assets/images/units/unit-zhao-yun-actions.png differ diff --git a/src/assets/images/units/unit-zhao-yun.png b/src/assets/images/units/unit-zhao-yun.png index d807b42..b489572 100644 Binary files a/src/assets/images/units/unit-zhao-yun.png and b/src/assets/images/units/unit-zhao-yun.png differ diff --git a/src/assets/images/units/unit-zhuge-liang-actions.png b/src/assets/images/units/unit-zhuge-liang-actions.png index d715d3b..669650b 100644 Binary files a/src/assets/images/units/unit-zhuge-liang-actions.png and b/src/assets/images/units/unit-zhuge-liang-actions.png differ diff --git a/src/assets/images/units/unit-zhuge-liang.png b/src/assets/images/units/unit-zhuge-liang.png index ca07770..24887f6 100644 Binary files a/src/assets/images/units/unit-zhuge-liang.png and b/src/assets/images/units/unit-zhuge-liang.png differ diff --git a/src/game/scenes/BattleScene.ts b/src/game/scenes/BattleScene.ts index 58ed2ed..d6f34c8 100644 --- a/src/game/scenes/BattleScene.ts +++ b/src/game/scenes/BattleScene.ts @@ -3199,7 +3199,6 @@ export class BattleScene extends Phaser.Scene { baseScaleY: sprite.scaleY }; this.unitViews.set(unit.id, view); - this.applyUnitTone(view); this.syncUnitMotion(unit, view); }); } @@ -8618,7 +8617,6 @@ export class BattleScene extends Phaser.Scene { return; } view.sprite.postFX.clear(); - this.applyUnitTone(view); view.sprite.clearTint(); view.sprite.setAlpha(1); if (unit) { @@ -9145,13 +9143,6 @@ export class BattleScene extends Phaser.Scene { }); } - private applyUnitTone(view: UnitView) { - const tone = view.sprite.postFX.addColorMatrix(); - tone.saturate(-0.32); - tone.contrast(0.03, true); - tone.brightness(0.97, true); - } - private isMountedUnit(unit: UnitData) { return unit.classKey === 'cavalry'; } @@ -9337,7 +9328,6 @@ export class BattleScene extends Phaser.Scene { } view.sprite.postFX.clear(); - this.applyUnitTone(view); view.sprite.clearTint(); view.sprite.setAlpha(1); this.syncUnitMotion(unit, view);