diff --git a/art/__pycache__/big_cases.cpython-314.pyc b/art/__pycache__/big_cases.cpython-314.pyc new file mode 100644 index 0000000..972e03c Binary files /dev/null and b/art/__pycache__/big_cases.cpython-314.pyc differ diff --git a/art/__pycache__/sprites.cpython-314.pyc b/art/__pycache__/sprites.cpython-314.pyc index e88a153..7c4eabd 100644 Binary files a/art/__pycache__/sprites.cpython-314.pyc and b/art/__pycache__/sprites.cpython-314.pyc differ diff --git a/art/big_cases.py b/art/big_cases.py new file mode 100644 index 0000000..ee2d3d9 --- /dev/null +++ b/art/big_cases.py @@ -0,0 +1,1159 @@ + +"""显卡检视大图叠加层:用于放大镜检视台的各种真假/成色鉴定 case 细节层。 +与底图同尺寸(192×128),仅绘制发生变化的像素。 +""" + +import math +import random +from big import ( + BW, + BH, + FANS, + FR, + NOTCH_X, + SH0, + SH1, + FING_Y0, + FING_Y1, + Canvas, + text57, + F57, +) + + +def _new(): + return Canvas(BW, BH) + + +# ============================================================================== +# 正面 Case +# ============================================================================== + + +def fan_dust1(): + """1. 风扇轻度积灰:叶片边缘灰线、轴心轻微积垢、少量蛛丝细线。""" + c = _new() + rnd = random.Random(101) + + for cx, cy in FANS: + # 轴心周围微灰圈 + for a_deg in range(0, 360, 15): + rad = math.radians(a_deg) + r = 7.0 + (rnd.random() * 2.5) + x, y = int(cx + math.cos(rad) * r), int(cy + math.sin(rad) * r) + c.put(x, y, "m" if rnd.random() < 0.65 else "d") + + # 九片叶片的前缘微量积灰与边角聚灰 + for blade in range(9): + base_ang = blade * (2 * math.pi / 9) + for r in range(10, FR - 4, 2): + ang = base_ang - (r - 7) * 0.055 + x = int(cx + math.cos(ang) * r) + y = int(cy + math.sin(ang) * r) + if rnd.random() < 0.40: + c.put(x, y, "b" if rnd.random() < 0.6 else "m") + # 叶尖处积微灰 + if r > FR - 8 and rnd.random() < 0.55: + c.put(x + 1, y, "l" if rnd.random() < 0.3 else "m") + + # 2~3 根搭在扇叶与风道外框之间的微细蛛丝 + for p0, p1 in ( + ((cx - 18, cy - 14), (cx - 25, cy - 10)), + ((cx + 10, cy + 18), (cx + 22, cy + 14)), + ): + x0, y0 = p0 + x1, y1 = p1 + steps = max(abs(x1 - x0), abs(y1 - y0)) + for i in range(steps + 1): + t = i / steps + sx = int(x0 + (x1 - x0) * t) + sy = int(y0 + (y1 - y0) * t + math.sin(t * math.pi) * 1.5) + c.put(sx, sy, "l" if i % 2 == 0 else "b") + + return c + + +def fan_dust2(): + """1. 风扇重度积灰:轴心厚灰结垢、叶面大团絮状灰斑、风道外圈堵灰、蜘蛛网细丝。""" + c = _new() + rnd = random.Random(102) + + for cx, cy in FANS: + # 轴心及周边重垢厚积 + for dy in range(-12, 13): + for dx in range(-12, 13): + r = math.hypot(dx, dy) + if 5.5 <= r <= 13.0: + val = rnd.random() + if val < 0.70: + c.put( + cx + dx, + cy + dy, + "b" if val < 0.25 else "m" if val < 0.55 else "d", + ) + + # 扇叶大面积覆灰与灰絮团 + for blade in range(9): + base_ang = blade * (2 * math.pi / 9) + for r in range(8, FR - 3): + ang = base_ang - (r - 7) * 0.055 + x = int(cx + math.cos(ang) * r) + y = int(cy + math.sin(ang) * r) + c.put(x, y, "b" if rnd.random() < 0.4 else "m") + if rnd.random() < 0.35: + c.put(x, y + 1, "d") + + # 风道死角与外圈凹陷堵灰 + for a_deg in range(0, 360, 4): + rad = math.radians(a_deg) + for dr in (FR - 6, FR - 5, FR - 4): + if rnd.random() < 0.65: + x = int(cx + math.cos(rad) * dr) + y = int(cy + math.sin(rad) * dr) + c.put(x, y, "d" if (x + y) % 2 else "m") + + # 灰絮团(带厚度高光) + clumps = ( + (cx - 14, cy - 8), + (cx + 12, cy - 14), + (cx - 8, cy + 15), + (cx + 15, cy + 12), + ) + for kx, ky in clumps: + c.rect(kx - 1, ky - 1, kx + 2, ky + 1, "m") + c.rect(kx - 1, ky - 1, kx + 1, ky - 1, "l") + c.put(kx + 2, ky + 1, "d") + c.put(kx - 2, ky, "b") + c.put(kx + 3, ky, "d") + + # 蛛网连线(从内到外蜘蛛网状蛛丝结构) + anchors = [ + (cx - 24, cy - 12), + (cx - 16, cy - 20), + (cx, cy - 25), + (cx + 18, cy - 18), + (cx - 12, cy - 5), + (cx + 8, cy - 8), + ] + edges = [(0, 4), (1, 4), (1, 5), (2, 5), (3, 5), (4, 5)] + for i0, i1 in edges: + x0, y0 = anchors[i0] + x1, y1 = anchors[i1] + steps = max(abs(x1 - x0), abs(y1 - y0)) + for s in range(steps + 1): + t = s / steps + sx = int(x0 + (x1 - x0) * t) + sy = int(y0 + (y1 - y0) * t) + c.put(sx, sy, "w" if s % 3 == 0 else "l") + + return c + + +def fan_chip(): + """2. 风扇叶片缺角:扇叶断裂缺损,断面 jagged 崩缺、露出黑风道底,带裂纹延伸至根部。""" + c = _new() + + # 左风扇断叶:位于右上方叶片(约 15°~45°) + cx, cy = FANS[0] + # 崩缺露出底部风道黑腔 + for r in range(16, FR - 2): + for deg in range(12, 44): + rad = math.radians(deg) + # 形成犬牙交错的不规则裂口形状 + r_edge = 18 + int(3 * math.sin(deg * 0.7) + 2 * math.cos(deg * 1.3)) + if r >= r_edge: + px = int(cx + math.cos(rad) * r) + py = int(cy + math.sin(rad) * r) + c.put(px, py, "n" if (px + py) % 3 else "k") + + # 断裂口侧缘受光白色高光毛刺与背光阴影 + break_edge = [ + (cx + 17, cy + 6), + (cx + 18, cy + 8), + (cx + 19, cy + 11), + (cx + 20, cy + 12), + (cx + 22, cy + 14), + (cx + 24, cy + 16), + (cx + 25, cy + 20), + ] + for i, (bx, by) in enumerate(break_edge): + c.put(bx, by, "h" if i % 2 == 0 else "w") + c.put(bx + 1, by + 1, "k") + + # 裂纹延伸(Stress crack)自断面一路裂向轴心根部 + crack = [ + (cx + 16, cy + 6), + (cx + 15, cy + 5), + (cx + 13, cy + 5), + (cx + 12, cy + 4), + (cx + 10, cy + 4), + (cx + 9, cy + 3), + (cx + 7, cy + 2), + ] + for kx, ky in crack: + c.put(kx, ky, "n") + c.put(kx, ky - 1, "l") # 裂缝边缘受光面 + + # 右风扇:叶尖崩掉一个小角 + rx, ry = FANS[1] + for r in range(FR - 8, FR - 2): + for deg in range(215, 235): + rad = math.radians(deg) + if r > FR - 6 + (deg % 3): + c.put( + int(rx + math.cos(rad) * r), + int(ry + math.sin(rad) * r), + "n", + ) + c.put(rx - 21, ry - 14, "h") + c.put(rx - 22, ry - 13, "w") + c.put(rx - 20, ry - 13, "k") + + return c + + +def fan_oil(): + """3. 风扇轴心漏油/褪色:轴承油渍沿离心方向与重力向下渗出浸润、轴心贴纸褪色混浊。""" + c = _new() + + for cx, cy in FANS: + # 轴心贴纸油污褪色(盖掉原来的鲜艳色,变暗浊褐灰) + for dy in range(-4, 5): + for dx in range(-4, 5): + r = math.hypot(dx, dy) + if r <= 4.2: + c.put(cx + dx, cy + dy, "e" if r < 2.5 else "d") + + # 轴心缝隙溢出的深色环状油垢 + for deg in range(0, 360, 10): + rad = math.radians(deg) + for r in (5.0, 6.0, 7.0): + ox = int(cx + math.cos(rad) * r) + oy = int(cy + math.sin(rad) * r) + c.put(ox, oy, "c" if deg % 20 == 0 else "e") + + # 向下及顺着离心叶片流淌的渗油泪痕(重力向下,沿扇叶根部流淌) + # 1) 主滴漏条(竖直向下) + drips = [ + (cx, cy + 7, "c"), + (cx + 1, cy + 7, "e"), + (cx, cy + 8, "c"), + (cx - 1, cy + 8, "q"), + (cx, cy + 9, "e"), + (cx, cy + 10, "c"), + (cx + 1, cy + 10, "h"), # 油液反光 + (cx, cy + 11, "e"), + (cx, cy + 12, "q"), + (cx, cy + 13, "e"), + (cx, cy + 14, "c"), + (cx, cy + 15, "h"), + (cx, cy + 16, "e"), + (cx + 1, cy + 17, "q"), + ] + for dx, dy, col in drips: + c.put(dx, dy, col) + + # 2) 右下斜向叶片根部浸润油晕 + side_drips = [ + (cx + 6, cy + 5, "e"), + (cx + 7, cy + 6, "c"), + (cx + 8, cy + 7, "q"), + (cx + 9, cy + 7, "h"), + (cx + 10, cy + 8, "e"), + (cx + 11, cy + 9, "c"), + (cx + 12, cy + 10, "e"), + (cx + 13, cy + 10, "q"), + ] + for dx, dy, col in side_drips: + c.put(dx, dy, col) + + # 3) 左上回渗微斑 + c.put(cx - 6, cy - 4, "e") + c.put(cx - 7, cy - 5, "q") + c.put(cx - 8, cy - 5, "c") + + return c + + +def fin_dim(): + """4. 金手指发暗:镀金磨损发褐,失去高光亮黄,露出发黑氧化的暗铜色和划轨。""" + c = _new() + x0, x1 = SH0[0], SH1[0] + + for x in range(x0 + 2, x1 - 2): + if NOTCH_X - 2 <= x <= NOTCH_X + 3 or (x - x0) % 4 == 3: + continue + pin_offset = (x - x0) % 4 + + # 顶部斜切高光被暗黄铜/暗灰取代 + c.put(x, FING_Y0, "q" if x % 2 == 0 else "m") + + # 针脚本体:失去 'Y',变为接触氧化的暗褐 'e'、暗铜 'q' 与焦褐 + for y in range(FING_Y0 + 1, FING_Y1): + # 模拟 PCIe 插拔划道痕迹(中间有极细竖向磨损深槽) + if pin_offset == 1 and y in (112, 113, 116, 117, 118, 120): + c.put(x, y, "c") # 磨损黑槽 + elif (x + y * 2) % 5 == 0: + c.put(x, y, "c") + elif (x + y) % 2 == 0: + c.put(x, y, "e") + else: + c.put(x, y, "q") + + # 底部插拔磨耗端 + c.put(x, FING_Y1, "c" if pin_offset == 0 else "e") + + return c + + +def fin_oxide(): + """5. 金手指氧化:铜绿由根部与底部向上爬蔓延,斑驳的蓝绿/深绿锈斑('G'/'g2'/'S')。""" + c = _new() + rnd = random.Random(205) + x0, x1 = SH0[0], SH1[0] + + # 定义几个主要锈蚀蔓延爆发区(树枝状爬生) + oxide_zones = [ + (35, 62, 11), # (x_start, x_end, max_h) + (78, 105, 8), + (125, 168, 13), + ] + + for x in range(x0 + 2, x1 - 2): + if NOTCH_X - 2 <= x <= NOTCH_X + 3 or (x - x0) % 4 == 3: + continue + + # 计算当前 x 的铜锈高度 + h_grow = 0 + for z0, z1, max_h in oxide_zones: + if z0 <= x <= z1: + mid = (z0 + z1) / 2 + span = (z1 - z0) / 2 + wave = math.cos((x - mid) / span * (math.pi / 2)) + h_grow = max( + h_grow, + int( + wave * max_h + + rnd.randint(-1, 2) + + (1 if x % 3 == 0 else 0) + ), + ) + + if h_grow > 0: + # 铜锈从底部根部 FING_Y1 往上爬 + for dy in range(h_grow + 1): + y = FING_Y1 - dy + if y < FING_Y0: + continue + # 锈壳中心粉绿 'S',主体 'G',深根 'g2' + if dy == h_grow: + col = "S" if rnd.random() < 0.4 else "G" + elif dy > h_grow // 2: + col = ( + "G" + if rnd.random() < 0.7 + else "S" + if rnd.random() < 0.5 + else "g2" + ) + else: + col = "g2" if rnd.random() < 0.8 else "c" + c.put(x, y, col) + + # 少量铜锈蔓延到相邻缝隙 + if (x - x0) % 4 == 2 and rnd.random() < 0.65: + c.put(x + 1, FING_Y1 - (h_grow // 2), "g2") + + return c + + +def brk_scratch(): + """6. 挡板划痕与凹坑:斜向金属切划痕(亮边+暗槽)与冲压碰伤凹坑。""" + c = _new() + + # 细划痕 1:贯穿上部金属区(斜向上提) + scratch1 = [ + (5, 18, "h"), + (6, 17, "w"), + (7, 16, "h"), + (8, 15, "w"), + (9, 14, "h"), + (10, 13, "l"), + (11, 12, "h"), + (12, 11, "k"), + ] + for x, y, col in scratch1: + c.put(x, y, col) + c.put(x, y + 1, "k") # 划痕背光刻沟 + + # 细划痕 2:接口 1 与 2 之间的斜割痕 + scratch2 = [ + (7, 31, "w"), + (8, 32, "h"), + (9, 32, "k"), + (10, 33, "h"), + (11, 33, "w"), + (12, 34, "h"), + (13, 35, "k"), + (14, 35, "h"), + (15, 36, "w"), + ] + for x, y, col in scratch2: + c.put(x, y, col) + c.put(x, y - 1, "d") + + # 细划痕 3:接口 2 与 3 之间十字交叉滑刀 + cross1 = [ + (6, 51, "h"), + (7, 52, "w"), + (8, 52, "h"), + (9, 53, "h"), + (10, 54, "w"), + (11, 54, "k"), + ] + cross2 = [ + (6, 54, "w"), + (7, 53, "h"), + (8, 53, "k"), + (9, 52, "h"), + (10, 51, "w"), + (11, 51, "h"), + ] + for x, y, col in cross1: + c.put(x, y, col) + for x, y, col in cross2: + c.put(x, y, col) + + # 细划痕 4:底部螺丝附近的起子滑刀伤 + slip = [ + (8, 103, "k"), + (9, 104, "w"), + (10, 104, "h"), + (11, 105, "w"), + (12, 105, "h"), + (13, 105, "k"), + (14, 106, "w"), + (15, 106, "h"), + ] + for x, y, col in slip: + c.put(x, y, col) + c.put(x, y + 1, "k") + + # 冲压小凹坑(小落伤,凹陷光影:左上暗槽、右下挤压高光圈) + pits = ((14, 22), (8, 72), (16, 75)) + for px, py in pits: + c.put(px, py, "k") + c.put(px + 1, py, "d") + c.put(px, py + 1, "d") + c.put(px + 1, py + 1, "w") + c.put(px + 2, py + 1, "h") + + return c + + +def brk_port(): + """7. 挡板接口数量不对:第三个接口被粗糙铁皮焊死/堵死,带焊渣点与开孔被封死。""" + c = _new() + y0, y1 = 56, 69 + + # 盖上一整块粗糙铁皮盲板封死 + c.rect(5, y0 - 1, 18, y1 + 1, "d") + c.rect(6, y0, 17, y1, "m") + + # 盲板拉丝与表面凹凸 + for x in range(6, 18): + for y in range(y0, y1 + 1): + if (x * 3 + y * 7) % 5 == 0: + c.put(x, y, "b") + elif (x + y) % 4 == 0: + c.put(x, y, "d") + + # 边缘粗糙焊缝与接合处阴影黑线 + for y in range(y0 - 1, y1 + 2): + c.put(5, y, "n") + c.put(18, y, "k") + for x in range(5, 19): + c.put(x, y0 - 1, "n") + c.put(x, y1 + 1, "k") + + # 两处粗糙固定冲压铆钉/点焊斑点 + for ry in (y0 + 2, y1 - 3): + c.rect(10, ry, 13, ry + 2, "k") + c.put(11, ry + 1, "b") + c.put(12, ry + 1, "h") + c.put(10, ry, "d") + + # 焊渣与高温变色痕(铜黄/焦色斑点) + weld_slag = [ + (5, y0 + 1, "e"), + (6, y0 + 1, "q"), + (17, y0 + 4, "e"), + (18, y0 + 5, "c"), + (6, y1 - 1, "q"), + (5, y1, "e"), + (18, y1 - 2, "c"), + ] + for sx, sy, scol in weld_slag: + c.put(sx, sy, scol) + + return c + + +def shroud_chip(): + """8. 散热罩磕碰/掉漆:外罩棱角撞击凹瘪、掉漆露出底铝银光与发散暗裂纹。""" + c = _new() + + # 1) 顶部主磕碰坑(x=80~90 处受剧烈撞击) + # 撞入深凹坑 + c.rect(81, 14, 88, 16, "k") + c.rect(82, 14, 87, 15, "n") + # 露出的底漆生铝金属高光反光 + c.rect(83, 16, 86, 17, "w") + c.put(82, 16, "h") + c.put(87, 16, "l") + # 漆皮外卷毛边 + for kx in range(80, 90): + c.put(kx, 13, "h" if kx % 2 == 0 else "l") + c.put(kx, 17, "k" if kx % 2 == 0 else "d") + # 撞击点向下延伸出的塑料/金属外壳发丝状应力裂纹 + crack1 = [ + (84, 18, "n"), + (84, 19, "k"), + (83, 20, "n"), + (83, 21, "k"), + (82, 22, "n"), + (81, 23, "k"), + (81, 24, "n"), + ] + for cx, cy, col in crack1: + c.put(cx, cy, col) + c.put(cx + 1, cy, "h") # 裂缝一侧高光 + + # 2) 中筋(两风扇之间)被工具磕掉漆皮 + c.rect(104, 46, 107, 51, "k") + c.rect(105, 47, 106, 49, "w") # 露底生铝 + c.put(106, 50, "h") + c.put(104, 45, "h") + c.put(107, 52, "d") + + # 3) 右上角倒角处擦碰 + c.rect(179, 17, 183, 20, "k") + c.put(180, 18, "w") + c.put(181, 19, "h") + c.put(182, 20, "l") + c.put(178, 16, "h") + + # 4) 下部边缘刮蹭掉漆痕 + c.rect(34, 93, 44, 94, "k") + for gx in range(35, 44, 2): + c.put(gx, 93, "w") + c.put(gx + 1, 94, "l") + + return c + + +# ============================================================================== +# 背面 Case +# ============================================================================== + + +def print_overlay(model_text, style="normal"): + """9. 型号丝印: + - normal: 激光蚀刻(深色凹槽衬底+规整高光金属字) + - skew: 字歪重印(各字上下抖动、墨色不均、重影移位、边缘溢墨) + - stamp: 盖章式补印(原字发暗底层+倾斜补印红框印章层覆盖) + """ + c = _new() + scale = 2 + # 丝印凹槽居中计算 + total_w = len(model_text) * (5 + 1) * scale + x_start = max(42, 38 + (136 - total_w) // 2) + y_start = 31 + + if style == "normal": + # 先打一层蚀刻内凹深色边缘刻痕 + text57( + c, + x_start + 1, + y_start + 1, + model_text, + "k", + scale=scale, + skew=False, + gap=1, + ) + # 精致激光银白字 + text57( + c, + x_start, + y_start, + model_text, + "h", + scale=scale, + skew=False, + gap=1, + ) + + elif style == "skew": + cur_x = x_start + rnd = random.Random(309) + jitters = [0, 2, -1, 1, -2, 2, 0, 1] + + # 1) 先打一层失准的底墨重影(偏移) + for i, ch in enumerate(model_text): + dy = jitters[i % len(jitters)] + # 偏色与残墨 + text57( + c, + cur_x + 1, + y_start + dy + 1, + ch, + "d", + scale=scale, + skew=False, + gap=1, + ) + cur_x += (5 + 1) * scale + (1 if i % 3 == 0 else 0) + + # 2) 正式墨迹(每字高度不齐、颜色深浅不同) + cur_x = x_start + ink_colors = ["h", "l", "b", "h", "m", "l"] + for i, ch in enumerate(model_text): + dy = jitters[i % len(jitters)] + col = ink_colors[i % len(ink_colors)] + text57( + c, + cur_x, + y_start + dy, + ch, + col, + scale=scale, + skew=False, + gap=1, + ) + + # 边缘溢墨斑点 (Ink bleed) + if ch != " ": + for _ in range(4): + bx = cur_x + rnd.randint(-1, 10) + by = y_start + dy + rnd.randint(-1, 14) + if 36 <= bx <= 178 and 26 <= by <= 50: + c.put(bx, by, "x" if rnd.random() < 0.5 else "d") + + cur_x += (5 + 1) * scale + (1 if i % 3 == 0 else 0) + + elif style == "stamp": + # 1) 底层被磨掉/发暗的原型号痕迹(原先低配型号残影) + orig_text = "RZX 50" if "80" in model_text else "PMD 60" + text57(c, x_start + 4, y_start + 1, orig_text, "z", scale=scale, gap=1) + text57(c, x_start + 5, y_start + 2, orig_text, "k", scale=scale, gap=1) + + # 2) 盖章边框(红章边框,微倾斜) + box_x0 = x_start - 4 + box_y0 = y_start - 3 + box_x1 = min(176, x_start + total_w + 4) + box_y1 = y_start + 17 + c.rect(box_x0, box_y0, box_x1, box_y0 + 1, "R") + c.rect(box_x0, box_y1 - 1, box_x1, box_y1, "R") + c.rect(box_x0, box_y0, box_x0 + 1, box_y1, "R") + c.rect(box_x1 - 1, box_y0, box_x1, box_y1, "R") + + # 章角溢印与盖印残红 + c.put(box_x0 - 1, box_y0, "r2") + c.put(box_x1 + 1, box_y1, "r2") + c.put(box_x0 + 1, box_y1 + 1, "r2") + + # 3) 盖印文字(红色印油,因印泥压力不均带斑驳漏白) + text57( + c, + x_start, + y_start, + model_text, + "R", + scale=scale, + skew=False, + gap=1, + ) + rnd = random.Random(409) + for y in range(box_y0, box_y1 + 1): + for x in range(box_x0, box_x1 + 1): + if c.px[y][x] == "R" and rnd.random() < 0.22: + c.put(x, y, "r2" if rnd.random() < 0.6 else "w") + + return c + + +def print_skew(model_text="RZX 80Ti"): + return print_overlay(model_text, "skew") + + +def print_stamp(model_text="RZX 80Ti"): + return print_overlay(model_text, "stamp") + + +def print_normal(model_text="RZX 80Ti"): + return print_overlay(model_text, "normal") + + +def sticker_hand(): + """10. 序列号贴纸:白胶条盖住原条码,上面粗劣手写伪造序列号。""" + c = _new() + + # 白胶带打底覆盖条码区域 (x=116..168, y=68..86) + c.rect(116, 68, 168, 86, "w") + # 胶带边缘立体层感与受光边 + c.rect(116, 68, 168, 68, "h") + c.rect(116, 86, 168, 86, "l") + c.rect(116, 68, 116, 86, "h") + c.rect(168, 68, 168, 86, "l") + + # 手写体字符 "SN:8942-X"(手写黑色笔画,带运笔粗细与倾斜波动) + strokes = [ + # S + (120, 72), + (121, 72), + (122, 72), + (119, 73), + (120, 74), + (121, 75), + (122, 76), + (119, 77), + (120, 78), + (121, 78), + # N + (125, 78), + (125, 77), + (125, 76), + (125, 75), + (125, 74), + (125, 73), + (125, 72), + (126, 74), + (127, 75), + (128, 76), + (129, 77), + (129, 72), + (129, 73), + (129, 74), + (129, 75), + (129, 76), + (129, 78), + # : + (132, 74), + (132, 77), + # 8 + (136, 72), + (137, 72), + (135, 73), + (138, 73), + (136, 75), + (137, 75), + (135, 76), + (138, 76), + (135, 77), + (138, 77), + (136, 78), + (137, 78), + # 9 + (142, 72), + (143, 72), + (141, 73), + (144, 73), + (141, 74), + (144, 74), + (142, 75), + (143, 75), + (144, 75), + (144, 76), + (144, 77), + (143, 78), + (142, 78), + # 4 + (147, 72), + (147, 73), + (147, 74), + (147, 75), + (148, 75), + (149, 75), + (150, 75), + (150, 72), + (150, 73), + (150, 74), + (150, 76), + (150, 77), + (150, 78), + # 2 + (153, 72), + (154, 72), + (155, 73), + (154, 74), + (153, 75), + (153, 76), + (153, 77), + (153, 78), + (154, 78), + (155, 78), + (156, 78), + # - + (158, 75), + (159, 75), + (160, 75), + # X + (162, 72), + (163, 73), + (164, 74), + (165, 76), + (166, 77), + (166, 78), + (166, 72), + (165, 73), + (164, 75), + (163, 77), + (162, 78), + ] + for x, y in strokes: + c.put(x, y, "O") + c.put(x + 1, y, "O") # 笔尖圆珠粗细 + c.put(x, y + 1, "k") # 圆珠笔纸面压痕阴影 + + return c + + +def sticker_scratch(): + """10. 序列号贴纸:条码被硬物反复恶意刮花破坏,白纸撕破、划痕露底。""" + c = _new() + + # 横向主刮痕(钥匙/一字起深划过,条码截断) + for x in range(116, 168): + c.put(x, 75, "w") + c.put(x, 76, "w") + c.put(x, 77, "h" if x % 3 == 0 else "l") + c.put(x, 78, "d" if x % 2 == 0 else "m") + + # 两道斜向猛烈刮叉痕 + slash1 = [ + (120, 70), + (123, 72), + (126, 74), + (130, 77), + (134, 80), + (138, 82), + (142, 84), + (145, 86), + ] + for x, y in slash1: + c.rect(x - 1, y - 1, x + 1, y, "w") + c.put(x + 2, y, "d") + c.put(x - 1, y + 1, "k") + + slash2 = [ + (160, 71), + (157, 73), + (153, 76), + (149, 79), + (145, 82), + (142, 84), + (138, 86), + ] + for x, y in slash2: + c.rect(x - 1, y - 1, x + 1, y, "w") + c.put(x + 1, y + 1, "k") + c.put(x - 2, y, "l") + + # 纸屑翻边卷毛 (Torn paper fibers) + for fx, fy in ( + (128, 74), + (132, 78), + (146, 83), + (152, 75), + (162, 74), + (121, 77), + ): + c.rect(fx, fy, fx + 1, fy + 1, "h") + c.put(fx, fy - 1, "w") + + return c + + +def sticker_torn(): + """10. 序列号贴纸:贴纸被撕掉一大半,留撕破犬牙撕口与发黄恶心残胶。""" + c = _new() + rnd = random.Random(510) + + # 撕裂区域:x=120..172, y=64..100(右侧大半被撕走,露出背板石墨底) + for y in range(64, 101): + # 锯齿状撕裂边界 x_tear + x_tear = 120 + int(3 * math.sin(y * 0.45) + (y % 4)) + # 撕除暴露出的背板底色(重现 backplate 拉丝暗底) + for x in range(x_tear, 173): + c.put(x, y, "d" if y % 2 else "m" if (x // 3) % 4 else "d") + + # 犬牙差互的白纸撕口边缘 (White torn paper fringe) + c.put(x_tear - 2, y, "w") + c.put(x_tear - 1, y, "h") + c.put(x_tear, y, "l") + c.put(x_tear + 1, y, "d") + + # 背板上残留的大片发干、粘着灰尘的胶痕(残胶:'e', 'q', 'm', 'd', 'k') + glue_patches = [ + (126, 68, 142, 82), + (148, 72, 168, 92), + (132, 84, 150, 96), + ] + for gx0, gy0, gx1, gy1 in glue_patches: + for gy in range(gy0, gy1 + 1): + for gx in range(gx0, gx1 + 1): + val = rnd.random() + if val < 0.55: + c.put( + gx, + gy, + ( + "e" + if val < 0.20 + else "q" + if val < 0.35 + else "m" + if val < 0.48 + else "k" + ), + ) + + # 没撕干净的局部纸片孤岛 + c.rect(156, 82, 165, 87, "w") + c.rect(157, 83, 164, 86, "h") + c.put(166, 88, "d") + + return c + + +def seal_missing(): + """11. 封条缺失:防拆封条被撕除,留边缘红碎纸片、底层 honeycomb/VOID 残胶与刮痕。""" + c = _new() + # 封条原本位置: x=174..182, y=60..104 + + # 露出底板金属 + for y in range(60, 105): + for x in range(174, 183): + c.put(x, y, "d" if y % 2 else "m" if (x // 3) % 4 else "d") + + # 顶部和底部断裂未撕净的红色封条碎片 (Torn seal scraps) + c.rect(174, 60, 182, 63, "R") + c.put(174, 64, "R") + c.put(175, 64, "r2") + c.put(178, 64, "R") + c.put(181, 64, "r2") + + c.rect(174, 102, 182, 104, "R") + c.put(176, 101, "R") + c.put(177, 101, "r2") + c.put(180, 101, "R") + + # 撕裂防伪胶转移层遗留的网格残胶斑(VOID 格状残留胶质) + for y in range(65, 101): + for x in range(174, 183): + # 规则点阵中带撕损 + if (x + y) % 3 == 0: + c.put(x, y, "r2" if (x * y) % 2 == 0 else "e") + elif (x * 2 + y) % 5 == 0: + c.put(x, y, "m") + + # 指甲抠挖清理残胶的竖划痕 + for y in range(70, 95): + c.put(177, y, "h" if y % 3 == 0 else "k") + c.put(180, y, "k" if y % 2 == 0 else "d") + + return c + + +def seal_reglued(): + """11. 封条被重新粘过:封条贴歪、角落起翘卷边(带投影)、内含明显鼓起气泡与折痕。""" + c = _new() + + # 封条重贴发生偏斜(整体往左歪 1px,并露出右边缘的旧胶印) + # 旧胶缝留痕 + for y in range(60, 105): + c.put(182, y, "e" if y % 2 else "d") + + # 重新贴上的红封条(略微偏斜移位) + c.rect(173, 62, 181, 103, "R") + c.rect(173, 62, 174, 103, "r2") + c.rect(180, 62, 181, 103, "r2") + + # 上端角落起翘卷边 (Curled Dog-ear corner) + # 起翘角露出白色背胶与内卷高光 + c.put(179, 61, "w") + c.put(180, 60, "w") + c.put(181, 60, "h") + c.put(179, 62, "h") + c.put(180, 61, "l") + # 翘起卷角下方投下的深暗阴影 + c.put(177, 62, "n") + c.put(178, 62, "k") + c.put(178, 63, "n") + + # 起泡 1:中间圆形隆起气泡 (Air bubble 1) + bubble1 = [ + (176, 73, "l"), + (177, 73, "w"), + (178, 73, "h"), + (175, 74, "l"), + (176, 74, "R"), + (177, 74, "w"), + (178, 74, "R"), + (179, 74, "r2"), + (175, 75, "h"), + (176, 75, "R"), + (177, 75, "R"), + (178, 75, "r2"), + (179, 75, "k"), + (176, 76, "r2"), + (177, 76, "k"), + (178, 76, "r2"), + ] + for x, y, col in bubble1: + c.put(x, y, col) + + # 起泡 2:下部条状长气泡 (Air bubble 2) + bubble2 = [ + (175, 87, "w"), + (176, 87, "l"), + (175, 88, "h"), + (176, 88, "R"), + (177, 88, "r2"), + (175, 89, "h"), + (176, 89, "R"), + (177, 89, "k"), + (176, 90, "r2"), + ] + for x, y, col in bubble2: + c.put(x, y, col) + + # 被撕下时产生的死褶横折白印 (Crease stress marks) + for x in range(173, 182): + c.put(x, 81, "w" if x % 2 == 0 else "h") + c.put(x, 82, "r2") + c.put(x, 95, "h" if x % 3 == 0 else "w") + c.put(x, 96, "r2") + + return c + + +def screw_opened(): + """12. 背板螺丝被拆过: + - (174, 94) 右下螺丝十字孔严重拧花/滑丝,溢出金属毛刺,起子滑出刮花背板; + - (36, 24) 左上螺丝十字槽口豁开变形磨损; + - (36, 94) 左下螺丝换成了一颗不同款的一字平头生锈旧螺丝。 + """ + c = _new() + + # -------------------------------------------------------------------------- + # 1. 右下螺丝 (174, 94):十字彻底滑丝拧烂 (Stripped screw) + 滑刀大划痕 + # -------------------------------------------------------------------------- + sx, sy = 174, 94 + # 彻底磨平滑丝的中心烂圆坑 + c.rect(sx - 2, sy - 2, sx + 2, sy + 2, "k") + c.rect(sx - 1, sy - 1, sx + 1, sy + 1, "n") + # 被起子强行旋转挤压出来的银白色金属毛刺边缘 + c.put(sx - 2, sy - 1, "w") + c.put(sx - 1, sy - 2, "w") + c.put(sx + 2, sy, "h") + c.put(sx, sy + 2, "h") + c.put(sx + 1, sy + 1, "w") + c.put(sx - 2, sy + 2, "l") + # 螺丝刀猛烈滑出拧花槽、在背板上划出的一道深深弧形刀痕 + driver_slip = [ + (sx - 2, sy - 2, "w"), + (sx - 3, sy - 3, "h"), + (sx - 4, sy - 4, "w"), + (sx - 5, sy - 4, "k"), + (sx - 6, sy - 5, "w"), + (sx - 7, sy - 5, "h"), + (sx - 8, sy - 5, "k"), + (sx - 9, sy - 6, "h"), + (sx - 10, sy - 6, "w"), + (sx - 11, sy - 6, "k"), + ] + for px, py, pcol in driver_slip: + c.put(px, py, pcol) + c.put(px, py + 1, "k") # 划痕阴影 + + # -------------------------------------------------------------------------- + # 2. 左上螺丝 (36, 24):起子咬合磨损划口,槽角崩损 + # -------------------------------------------------------------------------- + tx, ty = 36, 24 + c.rect(tx - 1, ty - 1, tx + 1, ty + 1, "k") + c.put(tx, ty, "n") + c.put(tx - 2, ty, "w") # 槽口外翻高光 + c.put(tx + 2, ty, "h") + c.put(tx, ty - 2, "w") + c.put(tx, ty + 2, "k") + c.put(tx - 1, ty - 1, "l") + c.put(tx + 1, ty + 1, "d") + + # -------------------------------------------------------------------------- + # 3. 左下螺丝 (36, 94):被换成了一颗规格不一致的一字平头暗铜色旧螺丝 + # -------------------------------------------------------------------------- + lx, ly = 36, 94 + # 重新画一个完全不同的圆头一字锈螺丝(基调为暗铜色 'q'/'e') + c.rect(lx - 3, ly - 3, lx + 3, ly + 3, "e") + c.rect(lx - 3, ly - 3, lx - 1, ly - 3, "q") + c.rect(lx - 2, ly - 2, lx + 2, ly + 2, "q") + c.rect(lx + 2, ly + 2, lx + 3, ly + 3, "c") + # 一字槽(水平横槽,而不是十字孔) + c.rect(lx - 2, ly, lx + 2, ly, "n") + c.rect(lx - 2, ly - 1, lx + 2, ly - 1, "h") # 一字边缘受光 + c.rect(lx - 2, ly + 1, lx + 2, ly + 1, "c") # 一字边缘阴影 + + return c + + +# ============================================================================== +# 导出字典 +# ============================================================================== + +CASES = { + # 正面 + "gpu_big_ov_fan_dust1": fan_dust1, + "gpu_big_ov_fan_dust2": fan_dust2, + "gpu_big_ov_fan_chip": fan_chip, + "gpu_big_ov_fan_oil": fan_oil, + "gpu_big_ov_fin_dim": fin_dim, + "gpu_big_ov_fin_oxide": fin_oxide, + "gpu_big_ov_brk_scratch": brk_scratch, + "gpu_big_ov_brk_port": brk_port, + "gpu_big_ov_shroud_chip": shroud_chip, + # 背面 + "gpu_big_ov_print_skew": print_skew, + "gpu_big_ov_print_stamp": print_stamp, + "gpu_big_ov_print_normal": print_normal, + "gpu_big_ov_sticker_hand": sticker_hand, + "gpu_big_ov_sticker_scratch": sticker_scratch, + "gpu_big_ov_sticker_torn": sticker_torn, + "gpu_big_ov_seal_missing": seal_missing, + "gpu_big_ov_seal_reglued": seal_reglued, + "gpu_big_ov_screw_opened": screw_opened, +} + +__all__ = [ + "CASES", + "print_overlay", + "fan_dust1", + "fan_dust2", + "fan_chip", + "fan_oil", + "fin_dim", + "fin_oxide", + "brk_scratch", + "brk_port", + "shroud_chip", + "print_skew", + "print_stamp", + "print_normal", + "sticker_hand", + "sticker_scratch", + "sticker_torn", + "seal_missing", + "seal_reglued", + "screw_opened", +] diff --git a/art/sprites.py b/art/sprites.py index 01c3f99..f866b90 100644 --- a/art/sprites.py +++ b/art/sprites.py @@ -568,7 +568,13 @@ if __name__ == '__main__': canvas.png(os.path.join(out, name + '.png')) for name, make in OVERLAYS.items(): make().png(os.path.join(out, name + '.png')) - import big - for name, make in {**big.BIG, **big.BIG_OV}.items(): + import big, big_cases + for name, make in big.BIG.items(): make().png(os.path.join(out, name + '.png')) + for name, make in big_cases.CASES.items(): + if not name.startswith('gpu_big_ov_print_'): + make().png(os.path.join(out, name + '.png')) + for m in MODELS: + for style in ('normal', 'skew', 'stamp'): + big_cases.print_overlay(m, style).png(os.path.join(out, 'gpu_big_ov_print_%s_%s.png' % (style, key(m)))) print(out) diff --git a/src/Decentralized.Domain/CardLook.cs b/src/Decentralized.Domain/CardLook.cs index d05f80d..e4efa64 100644 --- a/src/Decentralized.Domain/CardLook.cs +++ b/src/Decentralized.Domain/CardLook.cs @@ -32,6 +32,19 @@ namespace Decentralized.Domain return new CardLook { Fan = D(0), Fingers = D(1), Bracket = D(2), Print = D(3), Sticker = D(4) }; } + // 外观维度对应卡的真实状态:价格、损耗、暴毙概率都随之变化,所以看外观就是在估价 + private static readonly double[] FanValue = { 1.00, 0.96, 0.88 }, FanWear = { 1.00, 1.10, 1.30 }, FanDeath = { 1.00, 1.00, 1.20 }; + private static readonly double[] FingerValue = { 1.00, 0.96, 0.88 }, FingerDeath = { 1.00, 1.10, 1.30 }; + + /// 外观对价值的折扣:风扇积灰 −4%、缺角 −12%;金手指发暗 −4%、氧化 −12%;挡板划痕 −2%;封条缺失(开过封)−6%。 + public double ValueFactor => FanValue[Fan] * FingerValue[Fingers] * (Bracket == 1 ? 0.98 : 1.0) * (Sticker == 2 ? 0.94 : 1.0); + + /// 每晚损耗倍数:风扇积灰散热差 ×1.1,缺角 ×1.3。 + public double WearFactor => FanWear[Fan]; + + /// 暴毙概率倍数:风扇缺角 ×1.2;金手指发暗 ×1.1、氧化 ×1.3(接触不良)。 + public double DeathFactor => FanDeath[Fan] * FingerDeath[Fingers]; + /// 只在假卡上出现的取值:玩家一旦看到,就能肯定是假的。 public bool HasFakeSign => Bracket == 2 || Print != 0 || Sticker == 1; @@ -87,8 +100,8 @@ namespace Decentralized.Domain return Math.Max(1, (long)Math.Round(spec.Price * f)); } - /// 真实价值(芯片型号 + 健康度)。 - public static long True(Unit u) => Of(u.FakeOf ?? u.Model, u.Health); + /// 真实价值(芯片型号 + 健康度 + 外观折扣)。 + public static long True(Unit u) => Math.Max(1, (long)Math.Round(Of(u.FakeOf ?? u.Model, u.Health) * u.Look.ValueFactor)); /// 标称价:贩子报的价,按标称型号算;二手卡也折旧,但只按贩子"自称"的健康度。 public static long Quoted(Unit u, double claimedHealth) => Of(u.Model, claimedHealth); diff --git a/src/Decentralized.Domain/Mining.cs b/src/Decentralized.Domain/Mining.cs index 50b3a82..0c2c8d2 100644 --- a/src/Decentralized.Domain/Mining.cs +++ b/src/Decentralized.Domain/Mining.cs @@ -103,14 +103,14 @@ namespace Decentralized.Domain public double DeathChance(ModuleBonus b) { double p = Tuning.DeathBase + Tuning.DeathWorn * Math.Pow(1 - Health / 100, 2); - return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death; + return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death * Look.DeathFactor; } /// 一夜的损耗与暴毙判定;返回是否在今晚暴毙。 public bool Night(ModuleBonus b, Rng rng) { if (Dead) return false; - Health = Math.Max(0, Health - Label.WearFactor * b.Wear); + Health = Math.Max(0, Health - Label.WearFactor * b.Wear * Look.WearFactor); if (rng.Chance(DeathChance(b))) { Dead = true; diff --git a/src/Decentralized/GpuInspectView.cs b/src/Decentralized/GpuInspectView.cs index 14df97e..f4499cd 100644 --- a/src/Decentralized/GpuInspectView.cs +++ b/src/Decentralized/GpuInspectView.cs @@ -58,6 +58,34 @@ namespace Decentralized }); } + /// 检视大图的叠加层。五个维度各自对应一种或几种细节,组合时再加几处同源的小细节(磕碰、开过壳的螺丝、重新粘过的封条)。 + public static List BigOverlays(GameItem item) + { + var o = new List(); + var u = Items.ToUnit(item); + if (u.Dead) return o; + var l = u.Look; + string P = "gpu_big_ov_"; + if (!Items.IsBack(item)) + { + if (l.Fan == 1) o.Add(P + (l.Fingers > 0 ? "fan_dust2" : "fan_dust1")); + if (l.Fan == 2) { o.Add(P + "fan_chip"); if (l.Fingers == 2) o.Add(P + "fan_oil"); } + if (l.Fingers == 1) o.Add(P + "fin_dim"); + if (l.Fingers == 2) o.Add(P + "fin_oxide"); + if (l.Bracket == 1) { o.Add(P + "brk_scratch"); if (l.Fan > 0) o.Add(P + "shroud_chip"); } + if (l.Bracket == 2) o.Add(P + "brk_port"); + } + else + { + string model = (l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model).ToLowerInvariant(); + o.Add(P + "print_" + (l.Print == 2 ? "skew_" : l.Print == 1 ? "stamp_" : "normal_") + model); + if (l.Print == 2) o.Add(P + "screw_opened"); // 重印过,说明拆开过 + if (l.Sticker == 1) o.Add(P + "sticker_hand"); + if (l.Sticker == 2) o.Add(P + (l.Print != 0 ? "seal_reglued" : "seal_missing")); + } + return o; + } + private void Build(InspectionUIManager m) { root = new GameObject("_PdGpuInspection", typeof(RectTransform)).GetComponent(); @@ -92,12 +120,11 @@ namespace Decentralized { foreach (Transform c in cardRoot) Destroy(c.gameObject); var keys = new List(); - string baseKey = Items.LookKeys(item, keys); - keys.Insert(0, baseKey); - foreach (var small in keys) + string baseKey = Items.LookKeys(item, keys); // 小图键名只用来取底图(品牌与正反面) + var layers = new List { "gpu_big_" + baseKey.Substring("gpu_".Length) }; + layers.AddRange(BigOverlays(item)); + foreach (var k in layers) { - // 检视用大图:键名对应小图(gpu_probidia_f → gpu_big_probidia_f,gpu_ov_fan1 → gpu_big_ov_fan1) - string k = small.StartsWith("gpu_ov_") ? "gpu_big_ov_" + small.Substring("gpu_ov_".Length) : "gpu_big_" + small.Substring("gpu_".Length); var sprite = Items.ModSprite(k); if (sprite == null) continue; var go = new GameObject(k, typeof(RectTransform), typeof(Image)); diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk1.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk1.png deleted file mode 100644 index 21e08d2..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk1.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk2.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk2.png deleted file mode 100644 index e804332..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk2.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_port.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_port.png new file mode 100644 index 0000000..697655e Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_port.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_scratch.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_scratch.png new file mode 100644 index 0000000..cce203e Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_brk_scratch.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan1.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan1.png deleted file mode 100644 index dbf02f7..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan1.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan2.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan2.png deleted file mode 100644 index 9933c6a..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan2.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_chip.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_chip.png new file mode 100644 index 0000000..f61d657 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_chip.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust1.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust1.png new file mode 100644 index 0000000..d6cefee Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust1.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust2.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust2.png new file mode 100644 index 0000000..32d2733 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_dust2.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_oil.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_oil.png new file mode 100644 index 0000000..4e37fdb Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fan_oil.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin1.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin1.png deleted file mode 100644 index 5f3eb74..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin1.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin2.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin2.png deleted file mode 100644 index 04de9f5..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin2.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_dim.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_dim.png new file mode 100644 index 0000000..cd9a6c9 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_dim.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_oxide.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_oxide.png new file mode 100644 index 0000000..abe8e80 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_fin_oxide.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz470.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz470.png new file mode 100644 index 0000000..23d18e1 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz470.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz580.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz580.png new file mode 100644 index 0000000..2a440ba Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz580.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz6800.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz6800.png new file mode 100644 index 0000000..cf272a8 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz6800.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz7900.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz7900.png new file mode 100644 index 0000000..4e6dfaa Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rz7900.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx50.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx50.png new file mode 100644 index 0000000..afd9621 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx50.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx60.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx60.png new file mode 100644 index 0000000..dd7b405 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx60.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx70.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx70.png new file mode 100644 index 0000000..932e7e3 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx70.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx80ti.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx80ti.png new file mode 100644 index 0000000..a65824e Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx80ti.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx90.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx90.png new file mode 100644 index 0000000..d9ad64a Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_normal_rzx90.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz470.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz470.png new file mode 100644 index 0000000..60d30b6 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz470.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz580.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz580.png new file mode 100644 index 0000000..4c959d5 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz580.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz6800.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz6800.png new file mode 100644 index 0000000..1d81cef Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz6800.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz7900.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz7900.png new file mode 100644 index 0000000..0a05090 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rz7900.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx50.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx50.png new file mode 100644 index 0000000..e281b2d Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx50.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx60.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx60.png new file mode 100644 index 0000000..1eab1c2 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx60.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx70.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx70.png new file mode 100644 index 0000000..7a30318 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx70.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx80ti.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx80ti.png new file mode 100644 index 0000000..dd69532 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx80ti.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx90.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx90.png new file mode 100644 index 0000000..51ae82e Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_skew_rzx90.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz470.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz470.png new file mode 100644 index 0000000..845c47f Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz470.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz580.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz580.png new file mode 100644 index 0000000..81f1a55 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz580.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz6800.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz6800.png new file mode 100644 index 0000000..24b0a15 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz6800.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz7900.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz7900.png new file mode 100644 index 0000000..f489c99 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rz7900.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx50.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx50.png new file mode 100644 index 0000000..a44d7af Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx50.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx60.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx60.png new file mode 100644 index 0000000..e4c5877 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx60.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx70.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx70.png new file mode 100644 index 0000000..b301cb9 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx70.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx80ti.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx80ti.png new file mode 100644 index 0000000..e967b3c Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx80ti.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx90.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx90.png new file mode 100644 index 0000000..4240368 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_print_stamp_rzx90.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_screw_opened.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_screw_opened.png new file mode 100644 index 0000000..3fb7a89 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_screw_opened.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_missing.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_missing.png new file mode 100644 index 0000000..a5a45d3 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_missing.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_reglued.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_reglued.png new file mode 100644 index 0000000..ab260be Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_seal_reglued.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_shroud_chip.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_shroud_chip.png new file mode 100644 index 0000000..92699a9 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_shroud_chip.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_hand.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_hand.png new file mode 100644 index 0000000..642447a Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_hand.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_scratch.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_scratch.png new file mode 100644 index 0000000..e313992 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_scratch.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_torn.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_torn.png new file mode 100644 index 0000000..f563a40 Binary files /dev/null and b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_sticker_torn.png differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk1.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk1.png deleted file mode 100644 index 14051a7..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk1.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk2.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk2.png deleted file mode 100644 index d934e9e..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_stk2.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz470.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz470.png deleted file mode 100644 index 55b73ba..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz470.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz580.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz580.png deleted file mode 100644 index f42f89e..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz580.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz6800.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz6800.png deleted file mode 100644 index 939e124..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz6800.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz7900.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz7900.png deleted file mode 100644 index 6dc73a5..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rz7900.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx50.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx50.png deleted file mode 100644 index 65f66cc..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx50.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx60.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx60.png deleted file mode 100644 index d91bf65..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx60.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx70.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx70.png deleted file mode 100644 index 0cd95fb..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx70.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx80ti.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx80ti.png deleted file mode 100644 index e6d8c83..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx80ti.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx90.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx90.png deleted file mode 100644 index 77e5d14..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txs_rzx90.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz470.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz470.png deleted file mode 100644 index 47acb85..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz470.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz580.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz580.png deleted file mode 100644 index 5777ff6..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz580.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz6800.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz6800.png deleted file mode 100644 index c17088c..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz6800.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz7900.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz7900.png deleted file mode 100644 index eac4089..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rz7900.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx50.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx50.png deleted file mode 100644 index c1d5cce..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx50.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx60.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx60.png deleted file mode 100644 index 383ebc5..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx60.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx70.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx70.png deleted file mode 100644 index 0aed346..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx70.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx80ti.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx80ti.png deleted file mode 100644 index 6d16b64..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx80ti.png and /dev/null differ diff --git a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx90.png b/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx90.png deleted file mode 100644 index 6639936..0000000 Binary files a/src/Decentralized/ModFiles/Textures/Items/gpu_big_ov_txt_rzx90.png and /dev/null differ diff --git a/tests/Decentralized.Domain.Tests/Program.cs b/tests/Decentralized.Domain.Tests/Program.cs index becffce..36b8d8b 100644 --- a/tests/Decentralized.Domain.Tests/Program.cs +++ b/tests/Decentralized.Domain.Tests/Program.cs @@ -156,6 +156,11 @@ internal static class Program var u = new Unit { Model = "RZX90", FakeOf = "RZX60", Health = 80 }; Check(CardValue.True(u) == CardValue.Of("RZX60", 80) && CardValue.Quoted(u, 80) == CardValue.Of("RZX90", 80), "真实价值按芯片型号,标称价按标称型号"); Check(CardValue.Quoted(u, 80) > CardValue.True(u) * 8, $"假 RZX 90 的标称价 {CardValue.Quoted(u, 80)} 远高于真值 {CardValue.True(u)}"); + var worn = new Unit { Model = "RZX70", Health = 100, Look = new CardLook { Fan = 2, Fingers = 2, Bracket = 1, Sticker = 2 } }; + Check(Near(CardLook.Decode("22102").ValueFactor, 0.88 * 0.88 * 0.98 * 0.94, 1e-9) && CardValue.True(worn) == (long)Math.Round(800 * 0.88 * 0.88 * 0.98 * 0.94), "外观折扣乘进真实价值:风扇缺角 + 金手指氧化 + 划痕 + 封条缺失"); + var clean = new Unit { Model = "RZX70", Health = 80 }; + var dusty = new Unit { Model = "RZX70", Health = 80, Look = new CardLook { Fan = 2, Fingers = 2 } }; + Check(dusty.DeathChance(ModuleBonus.None) > clean.DeathChance(ModuleBonus.None) * 1.5 && Near(CardLook.Decode("20000").WearFactor, 1.3, 1e-9), "风扇缺角、金手指氧化抬高暴毙概率与损耗"); Check(CardValue.Of("RZX70", 100) == 800 && CardValue.Of("RZX70", 0) == 200 && CardValue.Of("RZX70", 50) == 500, "健康 100 满价、0 剩 25%、50 为 62.5%"); });