Tiers drive physical traits and serial checks; guide item
Fans (1/2/3/3) and power connectors (6/8/8/8+8) follow the real chip's tier, so a fake shows its real tier physically. Serial numbers (brand prefix, tier code, factory code, four digits) are drawn on the sticker from card state; the label bar gets power-and-fans and serial rows, eight in total, with a framed panel. A graphics card appraisal guide item holds the rules. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
No files matched your search
@@ -7,8 +7,9 @@ import random
|
|||||||
from sprites import Canvas, C, key, MODELS
|
from sprites import Canvas, C, key, MODELS
|
||||||
|
|
||||||
BW, BH = 192, 128
|
BW, BH = 192, 128
|
||||||
FANS = ((68, 51), (142, 51))
|
# 风扇布局(按风扇数):中心与半径;FANS / FR 保留为双风扇的值,给叠加图模块当默认
|
||||||
FR = 30 # 风扇半径
|
FAN_LAYOUT = {1: ([(105, 55)], 34), 2: ([(68, 51), (142, 51)], 30), 3: ([(52, 51), (96, 51), (140, 51)], 21)}
|
||||||
|
FANS, FR = FAN_LAYOUT[2][0], FAN_LAYOUT[2][1]
|
||||||
SH0, SH1 = (24, 14), (186, 96) # 散热罩 左上 / 右下
|
SH0, SH1 = (24, 14), (186, 96) # 散热罩 左上 / 右下
|
||||||
FING_Y0, FING_Y1 = 109, 122
|
FING_Y0, FING_Y1 = 109, 122
|
||||||
NOTCH_X = 112
|
NOTCH_X = 112
|
||||||
@@ -94,9 +95,9 @@ def bracket(c):
|
|||||||
c.rect(9, 10, 14, 12, 'k')
|
c.rect(9, 10, 14, 12, 'k')
|
||||||
|
|
||||||
|
|
||||||
def fan(c, cx, cy, accent, accent_dark):
|
def fan(c, cx, cy, accent, accent_dark, R=None):
|
||||||
"""风扇:九片弯曲扇叶(前缘高光、叶面渐变、叶尖暗边),外圈带四个固定螺丝,轴心带品牌圆标。"""
|
"""风扇:九片弯曲扇叶(前缘高光、叶面渐变、叶尖暗边),外圈带四个固定螺丝,轴心带品牌圆标。"""
|
||||||
R = FR
|
R = R or FR
|
||||||
for y in range(cy - R - 1, cy + R + 2):
|
for y in range(cy - R - 1, cy + R + 2):
|
||||||
for x in range(cx - R - 1, cx + R + 2):
|
for x in range(cx - R - 1, cx + R + 2):
|
||||||
dx, dy = x - cx, y - cy
|
dx, dy = x - cx, y - cy
|
||||||
@@ -135,7 +136,10 @@ def fan(c, cx, cy, accent, accent_dark):
|
|||||||
c.put(sx, sy, 'g')
|
c.put(sx, sy, 'g')
|
||||||
|
|
||||||
|
|
||||||
def gpu_front(accent, accent_dark, brand_text, burnt=False):
|
def gpu_front(accent, accent_dark, brand_text, tier=1, burnt=False):
|
||||||
|
"""tier 决定实物特征:风扇数(1/2/3/3)与供电口(6 针 / 8 针 / 8 针 / 双 8 针)。"""
|
||||||
|
count = (1, 2, 3, 3)[tier]
|
||||||
|
fans, R = FAN_LAYOUT[count]
|
||||||
c = Canvas(BW, BH)
|
c = Canvas(BW, BH)
|
||||||
bracket(c)
|
bracket(c)
|
||||||
x0, y0 = SH0
|
x0, y0 = SH0
|
||||||
@@ -161,21 +165,26 @@ def gpu_front(accent, accent_dark, brand_text, burnt=False):
|
|||||||
c.put(x, y, 'x' if (x - (x1 - 18)) % 3 == 0 else 'g' if (x - (x1 - 18)) % 3 == 1 else 'n')
|
c.put(x, y, 'x' if (x - (x1 - 18)) % 3 == 0 else 'g' if (x - (x1 - 18)) % 3 == 1 else 'n')
|
||||||
c.rect(x1 - 20, y0 + 10, x1 - 19, y1 - 4, 'x')
|
c.rect(x1 - 20, y0 + 10, x1 - 19, y1 - 4, 'x')
|
||||||
# 风扇之间的中筋
|
# 风扇之间的中筋
|
||||||
c.rect(105, y0 + 8, 106, y1 - 5, 'k'); c.rect(107, y0 + 8, 107, y1 - 5, 'x')
|
for a, b in zip(fans, fans[1:]):
|
||||||
for cx, cy in FANS:
|
mx = (a[0] + b[0]) // 2 + 1
|
||||||
fan(c, cx, cy, accent, accent_dark)
|
c.rect(mx - 1, y0 + 8, mx, y1 - 5, 'k'); c.rect(mx + 1, y0 + 8, mx + 1, y1 - 5, 'x')
|
||||||
|
for cx, cy in fans:
|
||||||
|
fan(c, cx, cy, accent, accent_dark, R)
|
||||||
# 前沿斜切装饰条:品牌色 + 品牌字
|
# 前沿斜切装饰条:品牌色 + 品牌字
|
||||||
for x in range(x0 + 4, x1 - 20):
|
for x in range(x0 + 4, x1 - 20):
|
||||||
c.rect(x, y1 - 5, x, y1 - 3, accent if x % 11 else accent_dark)
|
c.rect(x, y1 - 5, x, y1 - 3, accent if x % 11 else accent_dark)
|
||||||
text57(c, 112, 84, brand_text, 'h')
|
text57(c, 136 if count == 1 else 112, 84, brand_text, 'h')
|
||||||
# 顶沿:四根铜热管端头与 8 针供电口
|
# 顶沿:四根铜热管端头与 8 针供电口
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
x = 38 + i * 9
|
x = 38 + i * 9
|
||||||
c.rect(x, 7, x + 6, y0 - 1, 'p'); c.rect(x, 7, x + 1, y0 - 1, 'h' if i == 0 else 'p')
|
c.rect(x, 7, x + 6, y0 - 1, 'p'); c.rect(x, 7, x + 1, y0 - 1, 'h' if i == 0 else 'p')
|
||||||
c.rect(x + 5, 7, x + 6, y0 - 1, 'q'); c.rect(x, 7, x + 6, 7, 'q')
|
c.rect(x + 5, 7, x + 6, y0 - 1, 'q'); c.rect(x, 7, x + 6, 7, 'q')
|
||||||
c.rect(112, 5, 154, y0 - 1, 'n'); c.rect(112, 5, 154, 6, 'z')
|
# 供电口:低端 6 针;中端、高端 8 针;旗舰两个 8 针
|
||||||
for i in range(8):
|
for left, pins in ((((118, 6),) if tier == 0 else ((112, 8),) if tier < 3 else ((78, 8), (126, 8)))):
|
||||||
c.rect(114 + i * 5, 7, 116 + i * 5, 9, 'k'); c.put(115 + i * 5, 8, 'Y')
|
right = left + pins * 5 + 2
|
||||||
|
c.rect(left, 5, right, y0 - 1, 'n'); c.rect(left, 5, right, 6, 'z')
|
||||||
|
for i in range(pins):
|
||||||
|
c.rect(left + 2 + i * 5, 7, left + 4 + i * 5, 9, 'k'); c.put(left + 3 + i * 5, 8, 'Y')
|
||||||
# PCB:阻焊绿、边缘高光、元件与走线
|
# PCB:阻焊绿、边缘高光、元件与走线
|
||||||
for y in range(y1 + 1, FING_Y0):
|
for y in range(y1 + 1, FING_Y0):
|
||||||
for x in range(x0, x1 + 1):
|
for x in range(x0, x1 + 1):
|
||||||
@@ -248,8 +257,6 @@ def sticker(c, seed):
|
|||||||
w = 1 + ((x * 7 + seed) % 3)
|
w = 1 + ((x * 7 + seed) % 3)
|
||||||
if (x * 5 + seed) % 4 != 0:
|
if (x * 5 + seed) % 4 != 0:
|
||||||
c.rect(x, 70, x, 84, 'n')
|
c.rect(x, 70, x, 84, 'n')
|
||||||
text57(c, 118, 88, "0X5A70", 'n')
|
|
||||||
c.rect(150, 88, 166, 94, 'm')
|
|
||||||
|
|
||||||
|
|
||||||
def seal(c):
|
def seal(c):
|
||||||
@@ -407,19 +414,12 @@ def ov_sticker(kind):
|
|||||||
|
|
||||||
BIG = {}
|
BIG = {}
|
||||||
for _b, (_a, _ad, _t) in {'probidia': ('G', 'g2', 'PROBIDIA'), 'pmd': ('R', 'r2', 'PMD')}.items():
|
for _b, (_a, _ad, _t) in {'probidia': ('G', 'g2', 'PROBIDIA'), 'pmd': ('R', 'r2', 'PMD')}.items():
|
||||||
BIG['gpu_big_%s_f' % _b] = (lambda a=_a, ad=_ad, t=_t: gpu_front(a, ad, t))
|
for _tier in range(4):
|
||||||
|
BIG['gpu_big_%s_f_t%d' % (_b, _tier)] = (lambda a=_a, ad=_ad, t=_t, k=_tier: gpu_front(a, ad, t, k))
|
||||||
BIG['gpu_big_%s_b' % _b] = (lambda a=_a, ad=_ad: gpu_back(a, ad))
|
BIG['gpu_big_%s_b' % _b] = (lambda a=_a, ad=_ad: gpu_back(a, ad))
|
||||||
BIG['gpu_big_burnt_f'] = lambda: gpu_front('e', 'c', 'PROBIDIA', burnt=True)
|
BIG['gpu_big_burnt_f'] = lambda: gpu_front('e', 'c', 'PROBIDIA', 1, burnt=True)
|
||||||
BIG['gpu_big_burnt_b'] = lambda: gpu_back('e', 'c', burnt=True)
|
BIG['gpu_big_burnt_b'] = lambda: gpu_back('e', 'c', burnt=True)
|
||||||
BIG_OV = {
|
BIG_OV = {}
|
||||||
'gpu_big_ov_fan1': lambda: ov_fan(1), 'gpu_big_ov_fan2': lambda: ov_fan(2),
|
|
||||||
'gpu_big_ov_fin1': lambda: ov_fingers(1), 'gpu_big_ov_fin2': lambda: ov_fingers(2),
|
|
||||||
'gpu_big_ov_brk1': lambda: ov_bracket(1), 'gpu_big_ov_brk2': lambda: ov_bracket(2),
|
|
||||||
'gpu_big_ov_stk1': lambda: ov_sticker(1), 'gpu_big_ov_stk2': lambda: ov_sticker(2),
|
|
||||||
}
|
|
||||||
for _m in MODELS:
|
|
||||||
BIG_OV['gpu_big_ov_txt_' + key(_m)] = (lambda m=_m: ov_text(m, False))
|
|
||||||
BIG_OV['gpu_big_ov_txs_' + key(_m)] = (lambda m=_m: ov_text(m, True))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys, os
|
import sys, os
|
||||||
@@ -435,7 +435,5 @@ if __name__ == '__main__':
|
|||||||
b.px[y][x] = oc.px[y][x]
|
b.px[y][x] = oc.px[y][x]
|
||||||
return b
|
return b
|
||||||
bg = (0x6A, 0x72, 0x70)
|
bg = (0x6A, 0x72, 0x70)
|
||||||
stack('gpu_big_probidia_f').png(os.path.join(d, 'big_f.png'), scale=5, bg=bg)
|
for t in range(4):
|
||||||
stack('gpu_big_pmd_f', 'gpu_big_ov_fan1', 'gpu_big_ov_fin2', 'gpu_big_ov_brk2').png(os.path.join(d, 'big_f_fake.png'), scale=5, bg=bg)
|
stack('gpu_big_probidia_f_t%d' % t).png(os.path.join(d, 'big_f_t%d.png' % t), scale=3, bg=bg)
|
||||||
stack('gpu_big_pmd_b', 'gpu_big_ov_txs_rz6800', 'gpu_big_ov_stk1').png(os.path.join(d, 'big_b_fake.png'), scale=5, bg=bg)
|
|
||||||
stack('gpu_big_probidia_b', 'gpu_big_ov_txt_rzx80ti').png(os.path.join(d, 'big_b.png'), scale=5, bg=bg)
|
|
||||||
@@ -137,13 +137,14 @@ def bracket(c):
|
|||||||
c.put(2, 27, 'h'); c.put(4, 27, 'd')
|
c.put(2, 27, 'h'); c.put(4, 27, 'd')
|
||||||
|
|
||||||
|
|
||||||
def fan(c, cx, cy, accent, burnt=False):
|
def fan(c, cx, cy, accent, burnt=False, R=7):
|
||||||
"""风扇:深色风道里六片弯曲扇叶(前缘高光、叶面按受光渐变),外圈细边,轴心带品牌色点;光从左上来。"""
|
"""风扇:深色风道里六片弯曲扇叶(前缘高光、叶面按受光渐变),外圈细边,轴心带品牌色点;光从左上来。"""
|
||||||
import math
|
import math
|
||||||
for y in range(cy - 7, cy + 8):
|
k = 7.0 / R # 按半径折算到 R=7 的画法
|
||||||
for x in range(cx - 7, cx + 8):
|
for y in range(cy - R, cy + R + 1):
|
||||||
|
for x in range(cx - R, cx + R + 1):
|
||||||
dx, dy = x - cx, y - cy
|
dx, dy = x - cx, y - cy
|
||||||
r = math.hypot(dx, dy)
|
r = math.hypot(dx, dy) * k
|
||||||
if r > 7.4:
|
if r > 7.4:
|
||||||
continue
|
continue
|
||||||
ang = (math.atan2(dy, dx) / (2 * math.pi)) % 1.0
|
ang = (math.atan2(dy, dx) / (2 * math.pi)) % 1.0
|
||||||
@@ -164,7 +165,10 @@ def fan(c, cx, cy, accent, burnt=False):
|
|||||||
c.put(cx - 1, cy - 1, 'w')
|
c.put(cx - 1, cy - 1, 'w')
|
||||||
|
|
||||||
|
|
||||||
def gpu_front(accent, accent_dark, burnt=False):
|
FAN_LAYOUT_SMALL = {1: ([(26, 13)], 9), 2: ([(17, 13), (34, 13)], 7), 3: ([(14, 13), (26, 13), (38, 13)], 5)}
|
||||||
|
|
||||||
|
|
||||||
|
def gpu_front(accent, accent_dark, burnt=False, tier=1):
|
||||||
"""显卡正面(48×32,3×2 格),略微俯视:石墨色散热罩带斜切角与品牌色斜条,两个七叶风扇,
|
"""显卡正面(48×32,3×2 格),略微俯视:石墨色散热罩带斜切角与品牌色斜条,两个七叶风扇,
|
||||||
右端露出鳍片,顶沿露出铜热管和 8 针供电口,前沿是带元件的 PCB 和逐根画出的金手指。每格中心都不透明。"""
|
右端露出鳍片,顶沿露出铜热管和 8 针供电口,前沿是带元件的 PCB 和逐根画出的金手指。每格中心都不透明。"""
|
||||||
c = Canvas(W, H)
|
c = Canvas(W, H)
|
||||||
@@ -182,26 +186,33 @@ def gpu_front(accent, accent_dark, burnt=False):
|
|||||||
for y in range(TOP0 + 2, TOP1):
|
for y in range(TOP0 + 2, TOP1):
|
||||||
c.put(x, y, 'g' if (x - (R - 4)) % 2 == 0 else 'k')
|
c.put(x, y, 'g' if (x - (R - 4)) % 2 == 0 else 'k')
|
||||||
c.rect(R - 5, TOP0 + 2, R - 5, TOP1 - 1, 'x')
|
c.rect(R - 5, TOP0 + 2, R - 5, TOP1 - 1, 'x')
|
||||||
# 中间的筋条(两个风扇之间)与上下沿的槽
|
count = (1, 2, 3, 3)[tier]
|
||||||
for y in range(TOP0 + 3, TOP1 - 2):
|
fans, fr = FAN_LAYOUT_SMALL[count]
|
||||||
c.put(25, y, 'k'); c.put(26, y, 'x')
|
# 风扇之间的筋条
|
||||||
|
for a, b in zip(fans, fans[1:]):
|
||||||
|
mx = (a[0] + b[0]) // 2
|
||||||
|
for y in range(TOP0 + 3, TOP1 - 2):
|
||||||
|
c.put(mx, y, 'k'); c.put(mx + 1, y, 'x')
|
||||||
# 品牌色斜条(从前沿向左上延伸)与前沿色条
|
# 品牌色斜条(从前沿向左上延伸)与前沿色条
|
||||||
for x in range(L + 1, R - 5):
|
for x in range(L + 1, R - 5):
|
||||||
c.put(x, TOP1 - 1, accent if x % 9 else accent_dark)
|
c.put(x, TOP1 - 1, accent if x % 9 else accent_dark)
|
||||||
c.put(x, TOP1, accent_dark)
|
c.put(x, TOP1, accent_dark)
|
||||||
for cx, cy in FANS:
|
for cx, cy in fans:
|
||||||
fan(c, cx, cy, accent)
|
fan(c, cx, cy, accent, R=fr)
|
||||||
for dx, dy in ((-7, -7), (7, -7), (-7, 7), (7, 7)): # 风扇四角的固定孔
|
if count < 3:
|
||||||
c.put(cx + dx, cy + dy, 'n' if dx + dy else 'k')
|
for dx, dy in ((-7, -7), (7, -7), (-7, 7), (7, 7)): # 风扇四角的固定孔
|
||||||
|
c.put(cx + dx, cy + dy, 'n' if dx + dy else 'k')
|
||||||
# 顶沿:铜热管端头 + 8 针供电口(带针脚)
|
# 顶沿:铜热管端头 + 8 针供电口(带针脚)
|
||||||
for x0 in (L + 6, L + 8, L + 10, L + 12):
|
for x0 in (L + 6, L + 8, L + 10, L + 12):
|
||||||
c.put(x0, TOP0 - 1, 'p'); c.put(x0 + 1, TOP0 - 1, 'q')
|
c.put(x0, TOP0 - 1, 'p'); c.put(x0 + 1, TOP0 - 1, 'q')
|
||||||
for x in range(L + 18, L + 28):
|
# 供电口:低端 6 针;中端、高端 8 针;旗舰两个 8 针(每针占两像素)
|
||||||
c.put(x, TOP0 - 1, 'n')
|
for left, pins in (((L + 22, 6),) if tier == 0 else ((L + 18, 8),) if tier < 3 else ((L + 8, 8), (L + 25, 8))):
|
||||||
for x in range(L + 18, L + 28, 2):
|
for x in range(left, left + pins * 2):
|
||||||
c.put(x, TOP0 - 2, 'k')
|
c.put(x, TOP0 - 1, 'n')
|
||||||
for x in range(L + 19, L + 28, 2):
|
for x in range(left, left + pins * 2, 2):
|
||||||
c.put(x, TOP0 - 2, 'Y')
|
c.put(x, TOP0 - 2, 'k')
|
||||||
|
for x in range(left + 1, left + pins * 2, 2):
|
||||||
|
c.put(x, TOP0 - 2, 'Y')
|
||||||
# 前沿:PCB(绿)带元件,之后金手指
|
# 前沿:PCB(绿)带元件,之后金手指
|
||||||
for x in range(L, R + 1):
|
for x in range(L, R + 1):
|
||||||
c.put(x, TOP1 + 1, 'G' if x % 7 else 'g2'); c.put(x, TOP1 + 2, 'g2')
|
c.put(x, TOP1 + 1, 'G' if x % 7 else 'g2'); c.put(x, TOP1 + 2, 'g2')
|
||||||
@@ -221,7 +232,7 @@ def gpu_front(accent, accent_dark, burnt=False):
|
|||||||
c.put(x, y, 'c')
|
c.put(x, y, 'c')
|
||||||
for x in range(L + 1, R - 5):
|
for x in range(L + 1, R - 5):
|
||||||
c.put(x, TOP1 - 1, 'e')
|
c.put(x, TOP1 - 1, 'e')
|
||||||
for cx, cy in FANS:
|
for cx, cy in fans:
|
||||||
for dx, dy in ((0, 0), (1, 1), (-1, 1), (2, -2), (-2, -2)):
|
for dx, dy in ((0, 0), (1, 1), (-1, 1), (2, -2), (-2, -2)):
|
||||||
c.put(cx + dx, cy + dy, 'c')
|
c.put(cx + dx, cy + dy, 'c')
|
||||||
outline(c)
|
outline(c)
|
||||||
@@ -298,10 +309,10 @@ def overlay():
|
|||||||
return Canvas(W, H)
|
return Canvas(W, H)
|
||||||
|
|
||||||
|
|
||||||
def ov_fan(kind):
|
def ov_fan(kind, count=2):
|
||||||
"""风扇叠加:1 积灰(叶片上一层灰),2 叶片缺角(边缘缺一块并露出黑底)。"""
|
"""风扇叠加:1 积灰(叶片上一层灰),2 叶片缺角(边缘缺一块并露出黑底)。"""
|
||||||
c = overlay()
|
c = overlay()
|
||||||
for cx, cy in FANS:
|
for cx, cy in FAN_LAYOUT_SMALL[count][0]:
|
||||||
if kind == 1:
|
if kind == 1:
|
||||||
for dx, dy in ((-4, -2), (-2, -4), (3, -3), (4, 1), (-3, 3), (2, 4), (-5, 0), (0, 5), (1, -5), (-1, 2), (5, -1), (3, 2)):
|
for dx, dy in ((-4, -2), (-2, -4), (3, -3), (4, 1), (-3, 3), (2, 4), (-5, 0), (0, 5), (1, -5), (-1, 2), (5, -1), (3, 2)):
|
||||||
c.put(cx + dx, cy + dy, 'l')
|
c.put(cx + dx, cy + dy, 'l')
|
||||||
@@ -363,7 +374,7 @@ def ov_sticker(kind):
|
|||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
||||||
MODELS = ['RZX 50', 'RZX 60', 'RZX 70', 'RZX 80 Ti', 'RZX 90', 'RZ 470', 'RZ 580', 'RZ 6800', 'RZ 7900']
|
MODELS = ['RZX 60', 'RZX 70', 'RZX 80', 'RZX 90', 'RZ 70', 'RZ 80', 'RZ 800', 'RZ 900']
|
||||||
|
|
||||||
|
|
||||||
def rig():
|
def rig():
|
||||||
@@ -503,24 +514,43 @@ def key(model):
|
|||||||
return model.replace(' ', '').lower()
|
return model.replace(' ', '').lower()
|
||||||
|
|
||||||
|
|
||||||
|
def guide():
|
||||||
|
"""鉴定手册(16×16,一格):竖放的小册子,封面带品牌色条,书脊在左。"""
|
||||||
|
c = Canvas(16, 16)
|
||||||
|
c.box(2, 1, 13, 14, 'b')
|
||||||
|
c.rect(3, 2, 4, 13, 'd') # 书脊
|
||||||
|
c.rect(5, 2, 12, 2, 'h')
|
||||||
|
c.rect(6, 4, 11, 5, 'G') # 封面色块
|
||||||
|
c.rect(6, 4, 11, 4, 'g2')
|
||||||
|
for y in (7, 9, 11): # 文字行
|
||||||
|
c.rect(6, y, 11 if y != 11 else 9, y, 'm')
|
||||||
|
c.put(12, 13, 'd')
|
||||||
|
outline(c)
|
||||||
|
return c
|
||||||
|
|
||||||
|
|
||||||
SPRITES = {
|
SPRITES = {
|
||||||
'gpu_probidia_f': lambda: gpu_front('G', 'g2'),
|
'gpu_guide': guide,
|
||||||
'gpu_probidia_b': lambda: gpu_back('G', 'g2'),
|
|
||||||
'gpu_pmd_f': lambda: gpu_front('R', 'r2'),
|
|
||||||
'gpu_pmd_b': lambda: gpu_back('R', 'r2'),
|
|
||||||
'gpu_burnt_f': lambda: gpu_front('e', 'c', burnt=True),
|
'gpu_burnt_f': lambda: gpu_front('e', 'c', burnt=True),
|
||||||
'gpu_burnt_b': lambda: gpu_back('e', 'c', burnt=True),
|
'gpu_burnt_b': lambda: gpu_back('e', 'c', burnt=True),
|
||||||
|
'gpu_probidia_b': lambda: gpu_back('G', 'g2'),
|
||||||
|
'gpu_pmd_b': lambda: gpu_back('R', 'r2'),
|
||||||
'rig': rig,
|
'rig': rig,
|
||||||
'terminal': terminal,
|
'terminal': terminal,
|
||||||
}
|
}
|
||||||
|
for _tier in range(4):
|
||||||
|
SPRITES['gpu_probidia_f_t%d' % _tier] = (lambda t=_tier: gpu_front('G', 'g2', tier=t))
|
||||||
|
SPRITES['gpu_pmd_f_t%d' % _tier] = (lambda t=_tier: gpu_front('R', 'r2', tier=t))
|
||||||
|
|
||||||
# 叠加图:和底图同尺寸,位置 (0,0) 对齐,只画变化的像素,不参与判格
|
# 叠加图:和底图同尺寸,位置 (0,0) 对齐,只画变化的像素,不参与判格
|
||||||
OVERLAYS = {
|
OVERLAYS = {
|
||||||
'gpu_ov_fan1': lambda: ov_fan(1), 'gpu_ov_fan2': lambda: ov_fan(2),
|
|
||||||
'gpu_ov_fin1': lambda: ov_fingers(1), 'gpu_ov_fin2': lambda: ov_fingers(2),
|
'gpu_ov_fin1': lambda: ov_fingers(1), 'gpu_ov_fin2': lambda: ov_fingers(2),
|
||||||
'gpu_ov_brk1': lambda: ov_bracket(1), 'gpu_ov_brk2': lambda: ov_bracket(2),
|
'gpu_ov_brk1': lambda: ov_bracket(1),
|
||||||
'gpu_ov_stk1': lambda: ov_sticker(1), 'gpu_ov_stk2': lambda: ov_sticker(2),
|
'gpu_ov_stk2': lambda: ov_sticker(2),
|
||||||
}
|
}
|
||||||
|
for _n in (1, 2, 3):
|
||||||
|
OVERLAYS['gpu_ov_fan1_%d' % _n] = (lambda n=_n: ov_fan(1, n))
|
||||||
|
OVERLAYS['gpu_ov_fan2_%d' % _n] = (lambda n=_n: ov_fan(2, n))
|
||||||
for _m in MODELS:
|
for _m in MODELS:
|
||||||
OVERLAYS['gpu_ov_txt_' + key(_m)] = (lambda m=_m: ov_text(m, False))
|
OVERLAYS['gpu_ov_txt_' + key(_m)] = (lambda m=_m: ov_text(m, False))
|
||||||
OVERLAYS['gpu_ov_txs_' + key(_m)] = (lambda m=_m: ov_text(m, True))
|
OVERLAYS['gpu_ov_txs_' + key(_m)] = (lambda m=_m: ov_text(m, True))
|
||||||
@@ -551,13 +581,13 @@ if __name__ == '__main__':
|
|||||||
if oc.px[y][x] is not None:
|
if oc.px[y][x] is not None:
|
||||||
b.px[y][x] = oc.px[y][x]
|
b.px[y][x] = oc.px[y][x]
|
||||||
return b
|
return b
|
||||||
stack('gpu_probidia_f', 'gpu_ov_fan1', 'gpu_ov_fin1', 'gpu_ov_brk1').png(os.path.join(sys.argv[2], 'prev_front_worn.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
stack('gpu_probidia_f_t1', 'gpu_ov_fan2_2', 'gpu_ov_fin1', 'gpu_ov_brk1').png(os.path.join(sys.argv[2], 'prev_front_worn.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
||||||
stack('gpu_pmd_f', 'gpu_ov_fan2', 'gpu_ov_fin2', 'gpu_ov_brk2').png(os.path.join(sys.argv[2], 'prev_front_fake.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
|
||||||
stack('gpu_probidia_b', 'gpu_ov_txt_rzx80ti').png(os.path.join(sys.argv[2], 'prev_back_ok.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
|
||||||
stack('gpu_pmd_b', 'gpu_ov_txs_rz6800', 'gpu_ov_stk1', 'gpu_ov_stk2').png(os.path.join(sys.argv[2], 'prev_back_fake.png'), scale=6, bg=(0xA0, 0xA8, 0x9C))
|
|
||||||
print(sys.argv[2])
|
print(sys.argv[2])
|
||||||
else:
|
else:
|
||||||
out = os.path.normpath(os.path.join(here, '..', 'src', 'Decentralized', 'ModFiles', 'Textures', 'Items'))
|
out = os.path.normpath(os.path.join(here, '..', 'src', 'Decentralized', 'ModFiles', 'Textures', 'Items'))
|
||||||
|
for f in os.listdir(out): # 清掉旧的显卡图,避免留下不再使用的文件
|
||||||
|
if f.startswith('gpu_'):
|
||||||
|
os.remove(os.path.join(out, f))
|
||||||
for name, make in SPRITES.items():
|
for name, make in SPRITES.items():
|
||||||
canvas = make()
|
canvas = make()
|
||||||
check_cells(canvas, name)
|
check_cells(canvas, name)
|
||||||
@@ -568,8 +598,16 @@ if __name__ == '__main__':
|
|||||||
for name, make in big.BIG.items():
|
for name, make in big.BIG.items():
|
||||||
make().png(os.path.join(out, name + '.png'))
|
make().png(os.path.join(out, name + '.png'))
|
||||||
for name, make in big_cases.CASES.items():
|
for name, make in big_cases.CASES.items():
|
||||||
if not name.startswith('gpu_big_ov_print_'):
|
if name.startswith('gpu_big_ov_fan_'):
|
||||||
|
continue
|
||||||
|
if not name.startswith('gpu_big_ov_print_') and name in ('gpu_big_ov_fin_dim', 'gpu_big_ov_fin_oxide', 'gpu_big_ov_brk_scratch', 'gpu_big_ov_seal_missing'):
|
||||||
make().png(os.path.join(out, name + '.png'))
|
make().png(os.path.join(out, name + '.png'))
|
||||||
|
# 风扇叠加按风扇数各出一套:叠加模块里的风扇位置是模块级变量,换成对应布局后再画
|
||||||
|
for count, (centres, radius) in big.FAN_LAYOUT.items():
|
||||||
|
big_cases.FANS = list(centres) if len(centres) > 1 else [centres[0], centres[0]]
|
||||||
|
big_cases.FR = radius
|
||||||
|
for fname, short in (('fan_dust1', 'fan_dust1'), ('fan_dust2', 'fan_dust2'), ('fan_chip', 'fan_chip')):
|
||||||
|
getattr(big_cases, fname)().png(os.path.join(out, 'gpu_big_ov_%s_%d.png' % (short, count)))
|
||||||
for m in MODELS:
|
for m in MODELS:
|
||||||
for style in ('normal', 'skew', 'stamp'):
|
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))))
|
big_cases.print_overlay(m, style).png(os.path.join(out, 'gpu_big_ov_print_%s_%s.png' % (style, key(m))))
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ namespace Decentralized
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GpuInspectView : MonoBehaviour
|
public sealed class GpuInspectView : MonoBehaviour
|
||||||
{
|
{
|
||||||
private const float RowH = 30f, CardScale = 3f;
|
private const float RowH = 27f, CardScale = 2.7f, PanelTop = -86f;
|
||||||
|
private const int RowCount = 8;
|
||||||
private static GpuInspectView instance;
|
private static GpuInspectView instance;
|
||||||
private RectTransform root, cardRoot;
|
private RectTransform root, cardRoot;
|
||||||
private Button flip;
|
private Button flip;
|
||||||
@@ -26,9 +27,10 @@ namespace Decentralized
|
|||||||
private bool hidGlass;
|
private bool hidGlass;
|
||||||
private Transform buttonTemplate;
|
private Transform buttonTemplate;
|
||||||
private TMP_FontAsset font;
|
private TMP_FontAsset font;
|
||||||
private readonly TextMeshProUGUI[] rowName = new TextMeshProUGUI[6], rowText = new TextMeshProUGUI[6];
|
private readonly TextMeshProUGUI[] rowName = new TextMeshProUGUI[RowCount], rowText = new TextMeshProUGUI[RowCount];
|
||||||
private readonly Button[] rowButton = new Button[6];
|
private readonly Button[] rowButton = new Button[RowCount];
|
||||||
private readonly TextMeshProUGUI[] rowButtonText = new TextMeshProUGUI[6];
|
private readonly TextMeshProUGUI[] rowButtonText = new TextMeshProUGUI[RowCount];
|
||||||
|
private TextMeshProUGUI serialText;
|
||||||
|
|
||||||
public static void Ensure()
|
public static void Ensure()
|
||||||
{
|
{
|
||||||
@@ -83,18 +85,17 @@ namespace Decentralized
|
|||||||
string P = "gpu_big_ov_";
|
string P = "gpu_big_ov_";
|
||||||
if (!Items.IsBack(item))
|
if (!Items.IsBack(item))
|
||||||
{
|
{
|
||||||
if (l.Fan == 1) o.Add(P + "fan_dust2");
|
int n = Items.FansOf(u);
|
||||||
if (l.Fan == 2) { o.Add(P + "fan_dust1"); o.Add(P + "fan_chip"); }
|
if (l.Fan == 1) o.Add(P + "fan_dust2_" + n);
|
||||||
|
if (l.Fan == 2) { o.Add(P + "fan_dust1_" + n); o.Add(P + "fan_chip_" + n); }
|
||||||
if (l.Fingers == 1) o.Add(P + "fin_dim");
|
if (l.Fingers == 1) o.Add(P + "fin_dim");
|
||||||
if (l.Fingers == 2) o.Add(P + "fin_oxide");
|
if (l.Fingers == 2) o.Add(P + "fin_oxide");
|
||||||
if (l.Bracket == 1) o.Add(P + "brk_scratch");
|
if (l.Bracket == 1) o.Add(P + "brk_scratch");
|
||||||
if (l.Bracket == 2) o.Add(P + "brk_port");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string model = (l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model).ToLowerInvariant();
|
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);
|
o.Add(P + "print_" + (l.Print == 2 ? "skew_" : l.Print == 1 ? "stamp_" : "normal_") + model);
|
||||||
if (l.Sticker == 1) o.Add(P + "sticker_hand");
|
|
||||||
if (l.Sticker == 2) o.Add(P + "seal_missing");
|
if (l.Sticker == 2) o.Add(P + "seal_missing");
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
@@ -160,30 +161,40 @@ namespace Decentralized
|
|||||||
root.localPosition = Vector3.zero;
|
root.localPosition = Vector3.zero;
|
||||||
cardRoot = new GameObject("Card", typeof(RectTransform)).GetComponent<RectTransform>();
|
cardRoot = new GameObject("Card", typeof(RectTransform)).GetComponent<RectTransform>();
|
||||||
cardRoot.SetParent(root, false);
|
cardRoot.SetParent(root, false);
|
||||||
cardRoot.localPosition = new Vector3(0, 85, 0);
|
cardRoot.localPosition = new Vector3(0, 95, 0);
|
||||||
buttonTemplate = m.appraisalPanel.transform.Find("buttonSend");
|
buttonTemplate = m.appraisalPanel.transform.Find("buttonSend");
|
||||||
|
// 贴纸上的序列号:随卡变化,运行时用文字写在贴纸的空白处
|
||||||
|
serialText = MakeText(root, "Serial", Vector2.zero, new Vector2(48 * CardScale, 8 * CardScale), TextAlignmentOptions.Center, 20);
|
||||||
|
serialText.color = new Color(0.1f, 0.1f, 0.13f);
|
||||||
|
serialText.fontStyle = FontStyles.Bold;
|
||||||
|
serialText.overflowMode = TextOverflowModes.Overflow;
|
||||||
|
serialText.rectTransform.sizeDelta = new Vector2(48 * CardScale, 14 * CardScale);
|
||||||
if (buttonTemplate == null) return;
|
if (buttonTemplate == null) return;
|
||||||
font = buttonTemplate.GetComponentInChildren<TextMeshProUGUI>()?.font;
|
font = buttonTemplate.GetComponentInChildren<TextMeshProUGUI>()?.font;
|
||||||
|
if (font != null) serialText.font = font;
|
||||||
// 标签区:深色底加浅色边框,和上面的大图分开
|
// 标签区:深色底加浅色边框,和上面的大图分开
|
||||||
MakeRect(root, "LabelFrame", new Vector2(0, -201), new Vector2(648, 194), new Color(0.78f, 0.68f, 0.45f, 1f));
|
float panelH = RowCount * RowH + 10f, panelY = PanelTop - panelH / 2;
|
||||||
MakeRect(root, "LabelBack", new Vector2(0, -201), new Vector2(640, 186), new Color(0.10f, 0.11f, 0.14f, 0.96f));
|
MakeRect(root, "LabelFrame", new Vector2(0, panelY), new Vector2(648, panelH + 8), new Color(0.78f, 0.68f, 0.45f, 1f));
|
||||||
flip = MakeButton(root, "Flip", new Vector2(0, -326), new Vector2(200, 34), out flipText);
|
MakeRect(root, "LabelBack", new Vector2(0, panelY), new Vector2(640, panelH), new Color(0.10f, 0.11f, 0.14f, 0.96f));
|
||||||
|
flip = MakeButton(root, "Flip", new Vector2(0, PanelTop - panelH - 24), new Vector2(200, 30), out flipText);
|
||||||
flip.onClick.AddListener(() => { if (shown != null) Items.Flip(shown); });
|
flip.onClick.AddListener(() => { if (shown != null) Items.Flip(shown); });
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < RowCount; i++)
|
||||||
{
|
{
|
||||||
int row = CardLabels.Rows[i];
|
int row = CardLabels.Rows[i];
|
||||||
float y = -126 - i * RowH;
|
float y = PanelTop - 5 - RowH * (i + 0.5f);
|
||||||
rowName[i] = MakeText(root, "RowName" + i, new Vector2(-255, y), new Vector2(110, RowH), TextAlignmentOptions.Left, 24);
|
rowName[i] = MakeText(root, "RowName" + i, new Vector2(-255, y), new Vector2(110, RowH), TextAlignmentOptions.Left, 22);
|
||||||
rowText[i] = MakeText(root, "RowText" + i, new Vector2(-30, y), new Vector2(330, RowH), TextAlignmentOptions.Left, 24);
|
rowText[i] = MakeText(root, "RowText" + i, new Vector2(-30, y), new Vector2(330, RowH), TextAlignmentOptions.Left, 22);
|
||||||
rowButton[i] = MakeButton(root, "RowButton" + i, new Vector2(245, y), new Vector2(110, RowH - 4), out rowButtonText[i]);
|
rowButton[i] = MakeButton(root, "RowButton" + i, new Vector2(245, y), new Vector2(110, RowH - 3), out rowButtonText[i]);
|
||||||
rowButton[i].onClick.AddListener(() => Log.Guard("标签栏", () => OnRowButton(row)));
|
rowButton[i].onClick.AddListener(() => Log.Guard("标签栏", () => OnRowButton(row)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ValueText(int row, int value) =>
|
private static string RowKey(int row) => row == CardLabels.RowSpec ? "spec" : row == CardLabels.RowBuild ? "build" : row == CardLabels.RowFan ? "fan" : row == CardLabels.RowFingers ? "fingers"
|
||||||
row == CardLabels.RowSpec ? "" : L.T("lbl." + (row == CardLabels.RowFan ? "fan" : row == CardLabels.RowFingers ? "fingers" : row == CardLabels.RowBracket ? "bracket" : row == CardLabels.RowPrint ? "print" : "sticker") + "." + value);
|
: row == CardLabels.RowBracket ? "bracket" : row == CardLabels.RowPrint ? "print" : row == CardLabels.RowSerial ? "serial" : "seal";
|
||||||
|
|
||||||
private static string RowName(int row) => L.T("lbl.row." + (row == CardLabels.RowSpec ? "spec" : row == CardLabels.RowFan ? "fan" : row == CardLabels.RowFingers ? "fingers" : row == CardLabels.RowBracket ? "bracket" : row == CardLabels.RowPrint ? "print" : "sticker"));
|
private static string ValueText(int row, int value) => row == CardLabels.RowSpec ? "" : L.T("lbl." + RowKey(row) + "." + (row == CardLabels.RowSeal && value == 1 ? 0 : value));
|
||||||
|
|
||||||
|
private static string RowName(int row) => L.T("lbl.row." + RowKey(row));
|
||||||
|
|
||||||
/// <summary>现场有没有卖家 / 鉴定客户在:决定"指出"按钮是否出现。</summary>
|
/// <summary>现场有没有卖家 / 鉴定客户在:决定"指出"按钮是否出现。</summary>
|
||||||
private static bool CanPoint(GameItem item)
|
private static bool CanPoint(GameItem item)
|
||||||
@@ -203,37 +214,38 @@ namespace Decentralized
|
|||||||
int exposed = Items.Exposed(item);
|
int exposed = Items.Exposed(item);
|
||||||
bool owned = GeneralHelper.IsItemOwned(item);
|
bool owned = GeneralHelper.IsItemOwned(item);
|
||||||
bool canPoint = CanPoint(item), canEdit = owned && HasLabeler();
|
bool canPoint = CanPoint(item), canEdit = owned && HasLabeler();
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < RowCount; i++)
|
||||||
{
|
{
|
||||||
int row = CardLabels.Rows[i];
|
int row = CardLabels.Rows[i];
|
||||||
rowName[i].text = RowName(row);
|
rowName[i].text = RowName(row);
|
||||||
rowName[i].color = new Color(1f, 0.85f, 0.45f);
|
rowName[i].color = new Color(1f, 0.85f, 0.45f);
|
||||||
string text;
|
string text;
|
||||||
Color color = new Color(0.96f, 0.98f, 1f);
|
Color color = new Color(0.96f, 0.98f, 1f);
|
||||||
if (claim == null)
|
string Show(Claim c) => row == CardLabels.RowSpec ? DisplayModel(c.Model) : ValueText(row, c.Get(row));
|
||||||
{
|
if (claim == null) text = Show(real);
|
||||||
text = row == CardLabels.RowSpec ? DisplayModel(real.Model) : ValueText(row, real.Get(row));
|
|
||||||
}
|
|
||||||
else if ((exposed & row) != 0)
|
else if ((exposed & row) != 0)
|
||||||
{
|
{
|
||||||
int r = row == CardLabels.RowSpec ? 0 : real.Get(row);
|
text = Show(real);
|
||||||
text = row == CardLabels.RowSpec ? DisplayModel(real.Model) : ValueText(row, r);
|
bool lied = row == CardLabels.RowSpec ? claim.Value.Model != real.Model : claim.Value.Get(row) != real.Get(row);
|
||||||
bool lied = row == CardLabels.RowSpec ? claim.Value.Model != real.Model : claim.Value.Get(row) != r;
|
if (lied) { color = new Color(1f, 0.45f, 0.4f); text += L.T("lbl.said", row == CardLabels.RowBuild ? L.T("lbl.tier." + claim.Value.Tier) : Show(claim.Value)); }
|
||||||
if (lied) { color = new Color(1f, 0.45f, 0.4f); text += L.T("lbl.said", row == CardLabels.RowSpec ? DisplayModel(claim.Value.Model) : ValueText(row, claim.Value.Get(row))); }
|
|
||||||
else color = new Color(0.5f, 1f, 0.55f);
|
else color = new Color(0.5f, 1f, 0.55f);
|
||||||
}
|
}
|
||||||
else
|
else text = Show(claim.Value);
|
||||||
{
|
|
||||||
text = row == CardLabels.RowSpec ? DisplayModel(claim.Value.Model) : ValueText(row, claim.Value.Get(row));
|
|
||||||
}
|
|
||||||
rowText[i].text = text;
|
rowText[i].text = text;
|
||||||
rowText[i].color = color;
|
rowText[i].color = color;
|
||||||
bool show = row != CardLabels.RowSpec && ((canPoint && claim != null && (exposed & row) == 0) || canEdit || (canPoint && claim == null));
|
bool editable = row != CardLabels.RowBuild;
|
||||||
bool point = canPoint && !canEdit;
|
rowButton[i].gameObject.SetActive(canEdit ? editable : canPoint && (exposed & row) == 0);
|
||||||
rowButton[i].gameObject.SetActive(row != CardLabels.RowSpec ? ((canPoint && (exposed & row) == 0) || canEdit) : canEdit);
|
|
||||||
rowButtonText[i].text = L.T(canEdit ? "lbl.edit" : "lbl.point");
|
rowButtonText[i].text = L.T(canEdit ? "lbl.edit" : "lbl.point");
|
||||||
}
|
}
|
||||||
if (flipText != null) flipText.text = L.T(Items.IsBack(item) ? "inspect.flip.front" : "inspect.flip.back");
|
if (flipText != null) flipText.text = L.T(Items.IsBack(item) ? "inspect.flip.front" : "inspect.flip.back");
|
||||||
|
// 贴纸上的序列号:只在背面显示
|
||||||
|
if (serialText != null)
|
||||||
|
{
|
||||||
|
serialText.gameObject.SetActive(Items.IsBack(item) && !u.Dead);
|
||||||
|
serialText.text = CardLabels.SerialText(u);
|
||||||
|
// 贴纸空白处中心在大图 (142, 91):卡片坐标以图中心为原点,y 向上
|
||||||
|
serialText.rectTransform.localPosition = new Vector3((142 - 96) * CardScale, 95 + (64 - 91) * CardScale, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string DisplayModel(string model) => Items.DisplayModel(model);
|
private static string DisplayModel(string model) => Items.DisplayModel(model);
|
||||||
@@ -244,7 +256,7 @@ namespace Decentralized
|
|||||||
var item = shown;
|
var item = shown;
|
||||||
if (GeneralHelper.IsItemOwned(item))
|
if (GeneralHelper.IsItemOwned(item))
|
||||||
{
|
{
|
||||||
// 标签机:改说法,每按一次换下一个取值(型号是在九个型号里轮换)
|
// 标签机:改说法,每按一次换下一个取值(型号是在八个型号里轮换)
|
||||||
var u = Items.ToUnit(item);
|
var u = Items.ToUnit(item);
|
||||||
var cur = Items.GetClaim(item) ?? Claim.Truth(u);
|
var cur = Items.GetClaim(item) ?? Claim.Truth(u);
|
||||||
if (row == CardLabels.RowSpec)
|
if (row == CardLabels.RowSpec)
|
||||||
@@ -252,7 +264,7 @@ namespace Decentralized
|
|||||||
var models = Hardware.Specs.Values.Where(s => !s.Asic).Select(s => s.Model).ToList();
|
var models = Hardware.Specs.Values.Where(s => !s.Asic).Select(s => s.Model).ToList();
|
||||||
Items.EditClaim(item, row, 0, models[(models.IndexOf(cur.Model) + 1) % models.Count]);
|
Items.EditClaim(item, row, 0, models[(models.IndexOf(cur.Model) + 1) % models.Count]);
|
||||||
}
|
}
|
||||||
else Items.EditClaim(item, row, (cur.Get(row) + 1) % 3);
|
else Items.EditClaim(item, row, row == CardLabels.RowSeal ? (cur.Get(row) == 0 ? 2 : 0) : row == CardLabels.RowBracket ? (cur.Get(row) + 1) % 2 : (cur.Get(row) + 1) % 3);
|
||||||
EmporiumAudioPlayer.Instance?.audioLabeler?.Play();
|
EmporiumAudioPlayer.Instance?.audioLabeler?.Play();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
public const string Terminal = "pd_terminal";
|
public const string Terminal = "pd_terminal";
|
||||||
public const string Rig = "pd_rig";
|
public const string Rig = "pd_rig";
|
||||||
|
public const string Guide = "pd_gpu_guide";
|
||||||
public const string GpuPrefix = "pd_gpu_";
|
public const string GpuPrefix = "pd_gpu_";
|
||||||
|
|
||||||
public const string HealthTag = "PD_HEALTH";
|
public const string HealthTag = "PD_HEALTH";
|
||||||
@@ -36,6 +37,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
dir.Add(Terminal, CreateTerminal);
|
dir.Add(Terminal, CreateTerminal);
|
||||||
dir.Add(Rig, CreateRig);
|
dir.Add(Rig, CreateRig);
|
||||||
|
dir.Add(Guide, CreateGuide);
|
||||||
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic))
|
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic))
|
||||||
{
|
{
|
||||||
var s = spec;
|
var s = spec;
|
||||||
@@ -61,6 +63,20 @@ namespace Decentralized
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>显卡鉴定手册:档次对照、序列号规则、外观折扣。和游戏里的鉴定手册一样,是一件物品,说明里就是内容。</summary>
|
||||||
|
private static GameItem CreateGuide()
|
||||||
|
{
|
||||||
|
var item = ItemDirectory.CreateEmptyItem(Guide);
|
||||||
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, "gpu_guide");
|
||||||
|
item.name = L.T("item.guide.name");
|
||||||
|
item.shortDescription = L.T("item.guide.desc");
|
||||||
|
item.unitValue = 0;
|
||||||
|
item.EnableTag(GeneralHelper.IMPORTANT_TAG);
|
||||||
|
item.EnableTag(TypeHelper.NOT_FOR_RESALE);
|
||||||
|
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- 显卡 ----------
|
// ---------- 显卡 ----------
|
||||||
|
|
||||||
/// <summary>RZX70 → "RZX 70",RZ800 → "RZ 800"。</summary>
|
/// <summary>RZX70 → "RZX 70",RZ800 → "RZ 800"。</summary>
|
||||||
@@ -129,7 +145,7 @@ namespace Decentralized
|
|||||||
if ((lies & r) != 0 && rng.Chance(CustomerSpotChance))
|
if ((lies & r) != 0 && rng.Chance(CustomerSpotChance))
|
||||||
{
|
{
|
||||||
found |= r;
|
found |= r;
|
||||||
if (r != CardLabels.RowSpec && CardLabels.IsFakeSign(r, Claim.Truth(u).Get(r))) found |= CardLabels.RowSpec;
|
if (r != CardLabels.RowSpec && CardLabels.IsEvidence(r, claim.Value, Claim.Truth(u))) found |= CardLabels.RowSpec | CardLabels.RowBuild;
|
||||||
}
|
}
|
||||||
if (found == 0) return;
|
if (found == 0) return;
|
||||||
item.ModifyTag(ExposedTag, t => t.Enable().SetInt(exposed | found));
|
item.ModifyTag(ExposedTag, t => t.Enable().SetInt(exposed | found));
|
||||||
@@ -217,7 +233,7 @@ namespace Decentralized
|
|||||||
public static Unit ToUnit(GameItem item)
|
public static Unit ToUnit(GameItem item)
|
||||||
{
|
{
|
||||||
string model = item.identifier.Substring(GpuPrefix.Length);
|
string model = item.identifier.Substring(GpuPrefix.Length);
|
||||||
model = Hardware.Specs.Keys.First(k => k.ToLowerInvariant() == model);
|
model = Hardware.Specs.Keys.FirstOrDefault(k => k.ToLowerInvariant() == model) ?? "RZX60"; // 旧版本存档里的型号已改名,当作低端卡
|
||||||
var u = new Unit { Model = model, Health = 100 };
|
var u = new Unit { Model = model, Health = 100 };
|
||||||
if (item.IsTag(HealthTag)) u.Health = item.GetTagReadonly(HealthTag).GetDouble();
|
if (item.IsTag(HealthTag)) u.Health = item.GetTagReadonly(HealthTag).GetDouble();
|
||||||
if (item.IsTag(FakeTag)) u.FakeOf = item.GetTagReadonly(FakeTag).GetString();
|
if (item.IsTag(FakeTag)) u.FakeOf = item.GetTagReadonly(FakeTag).GetString();
|
||||||
@@ -253,7 +269,7 @@ namespace Decentralized
|
|||||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, item.IsTag(BackTag) ? "gpu_burnt_b" : "gpu_burnt_f");
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, item.IsTag(BackTag) ? "gpu_burnt_b" : "gpu_burnt_f");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item.SetSpriteAndShapeFromMod(ModInfo.Id, (label.Brand == Hardware.Probidia ? "gpu_probidia" : "gpu_pmd") + (item.IsTag(BackTag) ? "_b" : "_f"));
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, LookKeys(item, new List<string>()));
|
||||||
SyncValue(item);
|
SyncValue(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,6 +282,9 @@ namespace Decentralized
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>当前面的底图名与叠加图名:正面三个维度,背面丝印与贴纸;烧毁的卡不叠。</summary>
|
/// <summary>当前面的底图名与叠加图名:正面三个维度,背面丝印与贴纸;烧毁的卡不叠。</summary>
|
||||||
|
/// <summary>实物上的风扇数:由真实芯片的档次决定(低档次的板子套高档次的壳,风扇数露馅)。</summary>
|
||||||
|
public static int FansOf(Unit u) => Hardware.FanCount[Hardware.Specs[u.FakeOf ?? u.Model].Tier];
|
||||||
|
|
||||||
public static string LookKeys(GameItem item, List<string> overlays)
|
public static string LookKeys(GameItem item, List<string> overlays)
|
||||||
{
|
{
|
||||||
var u = ToUnit(item);
|
var u = ToUnit(item);
|
||||||
@@ -275,18 +294,18 @@ namespace Decentralized
|
|||||||
if (u.Dead) return back ? "gpu_burnt_b" : "gpu_burnt_f";
|
if (u.Dead) return back ? "gpu_burnt_b" : "gpu_burnt_f";
|
||||||
if (!back)
|
if (!back)
|
||||||
{
|
{
|
||||||
if (l.Fan > 0) overlays.Add("gpu_ov_fan" + l.Fan);
|
if (l.Fan > 0) overlays.Add($"gpu_ov_fan{l.Fan}_{FansOf(u)}");
|
||||||
if (l.Fingers > 0) overlays.Add("gpu_ov_fin" + l.Fingers);
|
if (l.Fingers > 0) overlays.Add("gpu_ov_fin" + l.Fingers);
|
||||||
if (l.Bracket > 0) overlays.Add("gpu_ov_brk" + l.Bracket);
|
if (l.Bracket > 0) overlays.Add("gpu_ov_brk1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 丝印:0 标称型号;1 印的是真实芯片型号;2 标称型号但字歪(重印过)
|
// 丝印:0 标称型号;1 印的是真实芯片型号;2 标称型号但字歪(重印过)
|
||||||
string model = l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model;
|
string model = l.Print == 1 && u.FakeOf != null ? u.FakeOf : u.Model;
|
||||||
overlays.Add((l.Print == 2 ? "gpu_ov_txs_" : "gpu_ov_txt_") + model.ToLowerInvariant());
|
overlays.Add((l.Print == 2 ? "gpu_ov_txs_" : "gpu_ov_txt_") + model.ToLowerInvariant());
|
||||||
if (l.Sticker > 0) overlays.Add("gpu_ov_stk" + l.Sticker);
|
if (l.Sticker == 2) overlays.Add("gpu_ov_stk2");
|
||||||
}
|
}
|
||||||
return brand + (back ? "_b" : "_f");
|
return brand + (back ? "_b" : "_f_t" + Hardware.Specs[u.FakeOf ?? u.Model].Tier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sprite ModSprite(string key)
|
public static Sprite ModSprite(string key)
|
||||||
|
|||||||
@@ -78,27 +78,15 @@ point.worn.1,"...Fine, it has that. I'll knock something off."
|
|||||||
point.worn.2,"Sharp eyes. All right, this price."
|
point.worn.2,"Sharp eyes. All right, this price."
|
||||||
point.fake.1,"...You caught it. It's a reflashed one. I'll price it for what it is."
|
point.fake.1,"...You caught it. It's a reflashed one. I'll price it for what it is."
|
||||||
point.fake.2,"Tch, not the original chip. Fine, the real chip's price."
|
point.fake.2,"Tch, not the original chip. Fine, the real chip's price."
|
||||||
lbl.row.spec,"Model"
|
|
||||||
lbl.row.fan,"Fans"
|
|
||||||
lbl.row.fingers,"Contacts"
|
|
||||||
lbl.row.bracket,"Bracket"
|
|
||||||
lbl.row.print,"Back print"
|
|
||||||
lbl.row.sticker,"Sticker"
|
|
||||||
lbl.fan.0,"Blades clean"
|
lbl.fan.0,"Blades clean"
|
||||||
lbl.fan.1,"Blades dusty"
|
lbl.fan.1,"Blades dusty"
|
||||||
lbl.fan.2,"Blade chipped"
|
lbl.fan.2,"Blade chipped"
|
||||||
lbl.fingers.0,"Bright"
|
lbl.fingers.0,"Bright"
|
||||||
lbl.fingers.1,"Dull"
|
lbl.fingers.1,"Dull"
|
||||||
lbl.fingers.2,"Oxidised"
|
lbl.fingers.2,"Oxidised"
|
||||||
lbl.bracket.0,"Intact, three ports"
|
|
||||||
lbl.bracket.1,"Scratched"
|
|
||||||
lbl.bracket.2,"Wrong port count"
|
|
||||||
lbl.print.0,"Matches the model"
|
lbl.print.0,"Matches the model"
|
||||||
lbl.print.1,"Another model printed"
|
lbl.print.1,"Another model printed"
|
||||||
lbl.print.2,"Reprinted, crooked"
|
lbl.print.2,"Reprinted, crooked"
|
||||||
lbl.sticker.0,"Printed serial, seal intact"
|
|
||||||
lbl.sticker.1,"Handwritten serial"
|
|
||||||
lbl.sticker.2,"Seal missing"
|
|
||||||
lbl.said," (seller said: {0})"
|
lbl.said," (seller said: {0})"
|
||||||
lbl.point,"Point out"
|
lbl.point,"Point out"
|
||||||
lbl.edit,"Edit"
|
lbl.edit,"Edit"
|
||||||
@@ -106,3 +94,28 @@ cust.fake.1,"That's not what the label says. You trying to pass off a fake?"
|
|||||||
cust.fake.2,"The model doesn't match. That isn't the chip it claims."
|
cust.fake.2,"The model doesn't match. That isn't the chip it claims."
|
||||||
cust.worn.1,"That's not what you wrote. You left out the flaws."
|
cust.worn.1,"That's not what you wrote. You left out the flaws."
|
||||||
cust.worn.2,"The condition on the label is false. Not at this price."
|
cust.worn.2,"The condition on the label is false. Not at this price."
|
||||||
|
lbl.row.spec,"Model"
|
||||||
|
lbl.row.build,"Power & fans"
|
||||||
|
lbl.row.fan,"Blades"
|
||||||
|
lbl.row.fingers,"Contacts"
|
||||||
|
lbl.row.bracket,"Bracket"
|
||||||
|
lbl.row.print,"Back print"
|
||||||
|
lbl.row.serial,"Serial"
|
||||||
|
lbl.row.seal,"Seal"
|
||||||
|
lbl.build.0,"Entry: 6-pin, single fan"
|
||||||
|
lbl.build.1,"Mid: 8-pin, two fans"
|
||||||
|
lbl.build.2,"High: 8-pin, three fans"
|
||||||
|
lbl.build.3,"Flagship: dual 8-pin, three fans"
|
||||||
|
lbl.bracket.0,"Intact"
|
||||||
|
lbl.bracket.1,"Scratched"
|
||||||
|
lbl.serial.0,"Valid"
|
||||||
|
lbl.serial.1,"Bad factory code or length"
|
||||||
|
lbl.serial.2,"Tier code does not match"
|
||||||
|
lbl.seal.0,"Intact"
|
||||||
|
lbl.seal.2,"Missing"
|
||||||
|
lbl.tier.0,"Entry"
|
||||||
|
lbl.tier.1,"Mid"
|
||||||
|
lbl.tier.2,"High"
|
||||||
|
lbl.tier.3,"Flagship"
|
||||||
|
item.guide.name,"Graphics card appraisal guide"
|
||||||
|
item.guide.desc,"Tiers: entry has a 6-pin connector and one fan; mid 8-pin and two fans; high 8-pin and three fans; flagship dual 8-pin and three fans. Model names are display only: Probidia RZX 60 / 70 / 80 / 90, PMD RZ 70 / 80 / 800 / 900, lowest to highest tier. Serial: prefix PB (Probidia) or MD (PMD), tier code 1 to 4, a dash, a two-digit factory code, a dash, four digits. Valid factory codes: PB 11, 12, 21, 34, 47; MD 13, 22, 35, 41, 58. A tier code that does not match the model, or a bad factory code or length, means a fake. Appearance discounts: dusty blades -4%, chipped -12%; dull contacts -4%, oxidised -12%; scratched bracket -2%; missing seal -6%."
|
||||||
|
@@ -77,27 +77,15 @@ point.worn.1,"……行,这点毛病是有,算你便宜点。"
|
|||||||
point.worn.2,"眼睛挺毒。好吧,这个价。"
|
point.worn.2,"眼睛挺毒。好吧,这个价。"
|
||||||
point.fake.1,"……被你看出来了。是翻新的货,按真的价给你。"
|
point.fake.1,"……被你看出来了。是翻新的货,按真的价给你。"
|
||||||
point.fake.2,"啧,不是原装的。那就按芯片本来的价吧。"
|
point.fake.2,"啧,不是原装的。那就按芯片本来的价吧。"
|
||||||
lbl.row.spec,"型号"
|
|
||||||
lbl.row.fan,"风扇"
|
|
||||||
lbl.row.fingers,"金手指"
|
|
||||||
lbl.row.bracket,"挡板"
|
|
||||||
lbl.row.print,"背面丝印"
|
|
||||||
lbl.row.sticker,"贴纸封条"
|
|
||||||
lbl.fan.0,"叶片干净"
|
lbl.fan.0,"叶片干净"
|
||||||
lbl.fan.1,"叶片积灰"
|
lbl.fan.1,"叶片积灰"
|
||||||
lbl.fan.2,"叶片缺角"
|
lbl.fan.2,"叶片缺角"
|
||||||
lbl.fingers.0,"光亮"
|
lbl.fingers.0,"光亮"
|
||||||
lbl.fingers.1,"发暗"
|
lbl.fingers.1,"发暗"
|
||||||
lbl.fingers.2,"氧化发绿"
|
lbl.fingers.2,"氧化发绿"
|
||||||
lbl.bracket.0,"完好,接口三个"
|
|
||||||
lbl.bracket.1,"有划痕"
|
|
||||||
lbl.bracket.2,"接口数不对"
|
|
||||||
lbl.print.0,"与型号一致"
|
lbl.print.0,"与型号一致"
|
||||||
lbl.print.1,"印着另一个型号"
|
lbl.print.1,"印着另一个型号"
|
||||||
lbl.print.2,"重印过,字歪"
|
lbl.print.2,"重印过,字歪"
|
||||||
lbl.sticker.0,"印刷序列号,封条完好"
|
|
||||||
lbl.sticker.1,"手写序列号"
|
|
||||||
lbl.sticker.2,"封条已缺失"
|
|
||||||
lbl.said,"(卖家说:{0})"
|
lbl.said,"(卖家说:{0})"
|
||||||
lbl.point,"指出"
|
lbl.point,"指出"
|
||||||
lbl.edit,"改"
|
lbl.edit,"改"
|
||||||
@@ -105,3 +93,28 @@ cust.fake.1,"这不是它标的那块。你拿假货糊弄我?"
|
|||||||
cust.fake.2,"型号对不上,里面的芯片根本不是这个。"
|
cust.fake.2,"型号对不上,里面的芯片根本不是这个。"
|
||||||
cust.worn.1,"跟你写的不一样,毛病你没说。"
|
cust.worn.1,"跟你写的不一样,毛病你没说。"
|
||||||
cust.worn.2,"标签上的成色是假的吧,这个价我不要。"
|
cust.worn.2,"标签上的成色是假的吧,这个价我不要。"
|
||||||
|
lbl.row.spec,"型号"
|
||||||
|
lbl.row.build,"供电与风扇"
|
||||||
|
lbl.row.fan,"叶片"
|
||||||
|
lbl.row.fingers,"金手指"
|
||||||
|
lbl.row.bracket,"挡板"
|
||||||
|
lbl.row.print,"背面丝印"
|
||||||
|
lbl.row.serial,"序列号"
|
||||||
|
lbl.row.seal,"封条"
|
||||||
|
lbl.build.0,"低端:6针,单风扇"
|
||||||
|
lbl.build.1,"中端:8针,双风扇"
|
||||||
|
lbl.build.2,"高端:8针,三风扇"
|
||||||
|
lbl.build.3,"旗舰:双8针,三风扇"
|
||||||
|
lbl.bracket.0,"完好"
|
||||||
|
lbl.bracket.1,"有划痕"
|
||||||
|
lbl.serial.0,"合规"
|
||||||
|
lbl.serial.1,"工厂码或位数不合规"
|
||||||
|
lbl.serial.2,"档次码与型号不符"
|
||||||
|
lbl.seal.0,"完好"
|
||||||
|
lbl.seal.2,"已缺失"
|
||||||
|
lbl.tier.0,"低端"
|
||||||
|
lbl.tier.1,"中端"
|
||||||
|
lbl.tier.2,"高端"
|
||||||
|
lbl.tier.3,"旗舰"
|
||||||
|
item.guide.name,"显卡鉴定手册"
|
||||||
|
item.guide.desc,"档次:低端 6 针供电、单风扇;中端 8 针、双风扇;高端 8 针、三风扇;旗舰双 8 针、三风扇。型号只是显示名:Probidia 为 RZX 60 / 70 / 80 / 90,PMD 为 RZ 70 / 80 / 800 / 900,按档次从低到高。序列号:前缀 PB(Probidia)或 MD(PMD),接档次码 1 至 4,一道横杠,两位工厂码,一道横杠,四位流水。合法工厂码:PB 为 11、12、21、34、47;MD 为 13、22、35、41、58。档次码与型号不符,或工厂码、位数不对,都是假的。外观折扣:叶片积灰 -4%,缺角 -12%;金手指发暗 -4%,氧化 -12%;挡板划痕 -2%;封条缺失 -6%。"
|
||||||
|
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 409 B |
|
After Width: | Height: | Size: 397 B |
|
After Width: | Height: | Size: 340 B |
|
After Width: | Height: | Size: 462 B |
|
After Width: | Height: | Size: 569 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 437 B |
|
Before Width: | Height: | Size: 431 B |
|
Before Width: | Height: | Size: 428 B |
|
After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 388 B |
|
After Width: | Height: | Size: 405 B |
|
After Width: | Height: | Size: 424 B |
|
Before Width: | Height: | Size: 451 B |
|
After Width: | Height: | Size: 428 B |
|
Before Width: | Height: | Size: 488 B |
|
Before Width: | Height: | Size: 569 B |
|
Before Width: | Height: | Size: 574 B |
|
Before Width: | Height: | Size: 634 B |
|
After Width: | Height: | Size: 502 B |
|
Before Width: | Height: | Size: 626 B |
|
After Width: | Height: | Size: 507 B |
|
After Width: | Height: | Size: 582 B |
|
After Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 592 B |
|
After Width: | Height: | Size: 592 B |
|
Before Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 876 B |
|
Before Width: | Height: | Size: 929 B |
|
After Width: | Height: | Size: 805 B |
|
Before Width: | Height: | Size: 905 B |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 903 B |
|
After Width: | Height: | Size: 883 B |
|
Before Width: | Height: | Size: 859 B |
|
After Width: | Height: | Size: 881 B |
|
Before Width: | Height: | Size: 966 B |
|
Before Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 419 B |
|
Before Width: | Height: | Size: 345 B |
|
Before Width: | Height: | Size: 441 B |
|
Before Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 1011 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 607 B After Width: | Height: | Size: 607 B |
|
After Width: | Height: | Size: 137 B |
|
Before Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 113 B |
|
After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 160 B |
|
Before Width: | Height: | Size: 155 B |
|
Before Width: | Height: | Size: 150 B |
|
Before Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 142 B |
|
Before Width: | Height: | Size: 156 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 150 B |
|
Before Width: | Height: | Size: 154 B |
|
After Width: | Height: | Size: 152 B |
|
Before Width: | Height: | Size: 164 B |
|
Before Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 141 B |
|
Before Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 136 B |
|
Before Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 138 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 140 B |
|
Before Width: | Height: | Size: 144 B |
|
After Width: | Height: | Size: 142 B |