Unveränderter Ausgangsstand inklusive Masterprompt und Konzeptbildern unter assets/. .godot/ und docs/screenshots/ bleiben laut .gitignore unversioniert; letztere sind unter ../backups gesichert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
180 lines
10 KiB
Python
180 lines
10 KiB
Python
"""Five mercenaries and the worker rebuilt around their actual icon silhouettes."""
|
|
from math import sin,cos,pi
|
|
from common import ellipsoid,ring,cylinder,beam,cone,box
|
|
from reference_geometry import r_plate,r_block,r_rock,r_sweep,r_lathe,r_band,r_disc,r_inset
|
|
|
|
|
|
def s_legs(m,heavy=False):
|
|
spread=.25 if heavy else .18
|
|
for s,side in [(-1,'L'),(1,'R')]:
|
|
hip=(s*spread*.65,.03,.63)
|
|
knee=(s*spread*1.10,.07,.37)
|
|
foot=(s*spread,-.05,.12)
|
|
r_band('Leg'+side+'_Thigh',hip,knee,.095 if heavy else .060,m['primary'],6)
|
|
r_band('Leg'+side+'_Shin',knee,foot,.080 if heavy else .049,m['primary'],6)
|
|
r_block('Leg'+side+'_Boot',(foot[0],-.11,.075),(.19 if heavy else .13,.29,.15),m['primary'])
|
|
if heavy:
|
|
r_plate('Leg'+side+'_KneePlate',(knee[0],-.02,knee[2]),[(-.115,.08),(.11,.08),(.11,-.045),(0,-.13),(-.12,-.04)],.10,m['primary'])
|
|
r_band('Leg'+side+'_Strap',(foot[0],-.05,.19),(foot[0],-.05,.245),.091,m['secondary'],6)
|
|
|
|
|
|
def s_mask(loc,m):
|
|
r_plate('Head_Visor',loc,[(-.12,.10),(0,.19),(.12,.10),(.10,-.10),(0,-.17),(-.10,-.10)],.13,m['light'],.028)
|
|
for s in [-1,1]:
|
|
r_plate('Head_Eye'+str(s),(loc[0]+s*.05,loc[1]-.098,loc[2]+.03),[(-.036,.013),(.036,.013),(s*.027,-.017)],.016,m['shadow'],.001)
|
|
r_band('Head_VisorSlit',(loc[0],loc[1]-.10,loc[2]+.015),(loc[0],loc[1]-.10,loc[2]-.135),.013,m['shadow'],4)
|
|
|
|
|
|
def s_hood(m,z=1.31):
|
|
r_rock('Head_HoodBack',(0,.04,z),(.20,.16,.25),m['primary'])
|
|
s_mask((0,-.10,z),m)
|
|
r_sweep('Head_HoodRim',[(-.14,-.18,z-.15),(-.17,-.17,z+.07),(-.10,-.12,z+.24),
|
|
(0,-.08,z+.29),(.14,-.16,z+.10),(.14,-.18,z-.15)],
|
|
[.045]*6,m['primary'],5)
|
|
r_sweep('Body_Scarf',[(-.18,-.03,z-.20),(0,-.14,z-.24),(.18,-.03,z-.20)],
|
|
[.05,.055,.04],m['accent'],5)
|
|
|
|
|
|
def s_arm(name,shoulder,elbow,hand,m,heavy=False):
|
|
r_band(name+'_Upper',shoulder,elbow,.085 if heavy else .053,m['primary'],6)
|
|
r_band(name+'_Lower',elbow,hand,.105 if heavy else .055,m['primary'],6)
|
|
r_rock(name+'_Glove',hand,(.115,.095,.095) if heavy else (.065,.055,.055),m['primary'])
|
|
if heavy:
|
|
r_block(name+'_Pauldron',shoulder,(.31,.32,.22),m['secondary'])
|
|
r_plate(name+'_PauldronCap',(shoulder[0],shoulder[1]-.17,shoulder[2]),
|
|
[(-.16,.095),(.16,.095),(.18,-.075),(-.18,-.075)],.055,m['primary'])
|
|
|
|
|
|
def s_heavy_torso(m):
|
|
r_inset('Body_Armor',(0,.035,.93),[(-.26,.23),(.26,.23),(.22,-.12),(0,-.29),(-.22,-.12)],
|
|
.34,m['secondary'],m['primary'])
|
|
r_block('Body_Belt',(0,0,.68),(.43,.32,.07),m['secondary'])
|
|
r_plate('Body_Tabard',(0,-.17,.49),[(-.095,.20),(.095,.20),(.12,-.10),(.02,-.25),(-.07,-.13)],.035,m['accent'])
|
|
r_rock('Head_HelmetBack',(0,.015,1.29),(.165,.16,.20),m['primary'])
|
|
s_mask((0,-.115,1.29),m)
|
|
r_plate('Head_Crest',(0,.015,1.45),[(-.022,-.09),(.022,-.09),(.025,.09),(-.02,.13)],.22,m['secondary'])
|
|
|
|
|
|
def s_scout(m):
|
|
s_legs(m)
|
|
r_plate('Body_LeatherCuirass',(0,.035,.93),[(-.19,.18),(.19,.18),(.13,-.24),(-.13,-.24)],.25,m['primary'])
|
|
s_hood(m)
|
|
r_band('Body_DiagonalBelt',(-.15,-.14,1.10),(.14,-.16,.77),.035,m['secondary'],4)
|
|
for s in [-1,1]:
|
|
r_plate('Body_SplitCoat'+str(s),(s*.15,.04,.62),[(-.09,.15),(.10,.15),(.16,-.20),(-.04,-.12)],.07,m['primary'])
|
|
r_sweep('Body_TornScarf'+str(s),[(s*.14,.13,1.16),(s*.23,.22,.94),(s*.43,.27,.72),(s*.54,.29,.57)],
|
|
[.07,.10,.07,0],m['accent'],5,ribbon=True)
|
|
for k in range(3):
|
|
r_band('Body_QuiverBolt'+str(k),(-.13+k*.07,.22,.95),(-.13+k*.07,.22,1.43),.022,m['secondary'],5)
|
|
s_arm('ArmL',(-.20,0,1.06),(-.27,-.11,.91),(-.06,-.23,.96),m)
|
|
s_arm('ArmR',(.20,0,1.06),(.30,-.08,.96),(.28,-.23,.98),m)
|
|
r_block('Weapon_CrossbowStock',(.16,-.22,.98),(.12,.53,.09),m['secondary'])
|
|
for s in [-1,1]:
|
|
points=[(.16,-.36,1.00),(.16+s*.20,-.35,1.00),(.16+s*.26,-.24,1.02)]
|
|
r_sweep('Weapon_Bow'+str(s),points,[.036,.035,.02],m['primary'],5)
|
|
r_band('Weapon_String'+str(s),points[-1],(.16,-.01,1.01),.009,m['light'],4)
|
|
r_band('Weapon_Bolt',(.16,-.03,1.045),(.16,-.67,1.045),.013,m['light'],4)
|
|
|
|
|
|
def s_tank(m):
|
|
s_legs(m,True); s_heavy_torso(m)
|
|
s_arm('ArmL',(-.30,.015,1.08),(-.42,-.035,.85),(-.40,-.10,.70),m,True)
|
|
s_arm('ArmR',(.30,.015,1.08),(.38,-.05,.90),(.30,-.22,.89),m,True)
|
|
r_inset('Weapon_TowerShield',(.28,-.33,.79),[(-.29,.48),(.29,.48),(.29,-.40),(.22,-.49),(-.22,-.49),(-.29,-.40)],
|
|
.12,m['light'],m['secondary'])
|
|
r_block('Weapon_ShieldSpine',(.28,-.432,.79),(.075,.055,.92),m['primary'])
|
|
r_rock('Weapon_ShieldBoss',(.28,-.51,.81),(.12,.14,.18),m['primary'])
|
|
for s in [-1,1]:
|
|
for z in [.40,1.16]:
|
|
r_block('Weapon_Corner'+str(s)+str(z),(.28+s*.23,-.44,z),(.13,.05,.11),m['light'])
|
|
|
|
|
|
def s_singer(m):
|
|
r_lathe('Body_LongRobe',(0,.03,.02),[(0,0),(.45,0),(.21,.83),(.18,1.13),(0,1.13)],m['primary'],segments=10)
|
|
s_hood(m,1.36)
|
|
for s in [-1,1]:
|
|
r_plate('Body_CreamStole'+str(s),(s*.11,-.22,.66),[(-.045,.43),(.045,.43),(.09,-.42),(0,-.53),(-.05,-.35)],.035,m['light'])
|
|
r_sweep('Body_RaggedCloak'+str(s),[(s*.18,.09,1.17),(s*.34,.15,.94),
|
|
(s*.41,.19,.64),(s*.52,.17,.30),(s*.41,.16,.06)],
|
|
[.09,.11,.12,.10,0],m['accent'],5,ribbon=True)
|
|
s_arm('ArmL',(-.18,0,1.10),(-.26,-.06,.89),(-.12,-.22,.81),m)
|
|
s_arm('ArmR',(.18,0,1.10),(.30,-.11,1.20),(.40,-.19,1.28),m)
|
|
axis=(1,-.16,.07)
|
|
r_lathe('Weapon_Trumpet',(.06,-.20,1.32),[(0,0),(.025,.015),(.038,.31),(.12,.56),(.23,.72),
|
|
(.18,.72),(.078,.55),(.022,.28),(0,.27)],m['secondary'],axis,10)
|
|
|
|
|
|
def s_hammer(m):
|
|
s_legs(m,True); s_heavy_torso(m)
|
|
s_arm('ArmL',(-.30,.02,1.08),(-.39,-.06,.90),(-.23,-.24,.84),m,True)
|
|
s_arm('ArmR',(.30,.02,1.08),(.36,-.08,1.00),(.30,-.27,1.04),m,True)
|
|
r_band('Weapon_Haft',(-.52,-.22,.70),(.54,-.30,1.19),.039,m['secondary'],8)
|
|
r_block('Weapon_Head',(.58,-.30,1.21),(.32,.34,.38),m['primary'])
|
|
# Solid sloping wedge and separate raised triangular engraving.
|
|
outline=[(-.19,.18),(.15,.26),(.26,-.04),(-.05,-.21),(-.19,-.09)]
|
|
r_plate('Weapon_Wedge',(.65,-.31,1.25),outline,.43,m['primary'])
|
|
r_plate('Weapon_TriangleRim',(.67,-.57,1.29),[(-.10,-.04),(.12,-.04),(.01,.15)],.024,m['light'])
|
|
r_plate('Weapon_TriangleInset',(.68,-.59,1.30),[(-.055,-.015),(.062,-.015),(.004,.09)],.025,m['primary'])
|
|
|
|
|
|
def s_rift(m):
|
|
s_legs(m)
|
|
# Four separate ribs leave an actual void through the chest.
|
|
for s in [-1,1]:
|
|
r_sweep('Body_HollowRib'+str(s),[(0,.03,.72),(s*.23,.02,.99),(s*.14,.02,1.23),(0,.025,1.29)],
|
|
[.06,.10,.11,.06],m['primary'],5)
|
|
r_sweep('Body_RiftEdge'+str(s),[(0,-.065,.80),(s*.14,-.08,.99),(s*.08,-.08,1.16)],
|
|
[.009,.012,.008],m['rift'],4)
|
|
r_plate('Body_TornCloth'+str(s),(s*.23,.055,.95),[(-.045,.28),(.055,.30),(.13,-.17),(.02,-.10),(-.06,-.28)],.025,m['secondary'])
|
|
r_plate('Body_HipRag'+str(s),(s*.15,.035,.56),[(-.05,.16),(.06,.17),(.12,-.20),(.03,-.13),(-.03,-.25)],.025,m['secondary'])
|
|
r_rock('Head_FacelessHelm',(0,.035,1.46),(.12,.10,.20),m['shadow'])
|
|
r_sweep('Head_MintCrack',[(-.025,-.076,1.57),(.028,-.081,1.44),(.01,-.078,1.29)],
|
|
[.012,.008,0],m['rift'],4)
|
|
for s in [-1,1]:
|
|
r_sweep('Head_Antler'+str(s),[(s*.08,.01,1.42),(s*.25,.01,1.56),
|
|
(s*.23,.025,1.73),(s*.17,.02,1.79)],
|
|
[.05,.065,.04,0],m['light'],5)
|
|
r_sweep('Head_InnerHorn'+str(s),[(s*.13,.035,1.54),(s*.14,.04,1.84)],
|
|
[.045,0],m['light'],5)
|
|
s_arm('ArmL',(-.19,.02,1.17),(-.31,0,.95),(-.38,-.08,.73),m)
|
|
s_arm('ArmR',(.19,.02,1.17),(.31,-.03,.99),(.43,-.12,1.13),m)
|
|
for j in range(3):
|
|
x=-.38+(j-1)*.035
|
|
r_sweep('ArmL_Claw'+str(j),[(x,-.08,.73),(x-.02,-.09,.63),(x+.025,-.1,.55)],[.015,.013,0],m['primary'],4)
|
|
r_rock('Weapon_RiftOrb',(.43,-.12,1.23),(.11,.09,.13),m['accent'])
|
|
r_rock('Weapon_RiftLight',(.43,-.202,1.23),(.07,.025,.095),m['rift'])
|
|
|
|
|
|
def s_worker(m):
|
|
# Squat clay body, oversized hood, apron, forked collector and round lantern.
|
|
ellipsoid('Body_Clay',(0,.025,.45),(.29,.21,.30),m['primary'],subdivisions=2)
|
|
for s,side in [(-1,'L'),(1,'R')]:
|
|
r_rock('Leg'+side+'_Foot',(s*.18,-.055,.075),(.17,.18,.10),m['primary'])
|
|
r_rock('Arm'+side+'_Shoulder',(s*.28,0,.64),(.13,.13,.15),m['primary'])
|
|
r_rock('Arm'+side+'_Hand',(s*.36,-.13,.59),(.13,.11,.12),m['primary'])
|
|
ellipsoid('Head_Hood',(0,.035,.96),(.31,.25,.32),m['secondary'],subdivisions=2)
|
|
ellipsoid('Head_ClayFace',(0,-.18,.96),(.24,.10,.245),m['primary'],subdivisions=2)
|
|
r_sweep('Head_HoodEdge',[(-.23,-.235,.80),(-.29,-.21,1.02),(-.17,-.18,1.21),(0,-.17,1.25),
|
|
(.17,-.18,1.21),(.29,-.21,1.02),(.23,-.235,.80)],
|
|
[.035]*7,m['secondary'],6)
|
|
for s in [-1,1]:
|
|
r_disc('Head_EyeSocket'+str(s),(s*.083,-.28,.99),.041,.023,m['shadow'])
|
|
r_rock('Head_Eye'+str(s),(s*.083,-.3,.99),(.022,.017,.028),m['light'])
|
|
r_band('Body_ApronStrap'+str(s),(s*.18,-.16,.72),(s*.18,-.17,.31),.025,m['secondary'],4)
|
|
r_block('Body_Buckle'+str(s),(s*.18,-.19,.67),(.065,.025,.07),m['accent'])
|
|
r_plate('Body_Apron',(0,-.19,.39),[(-.20,.25),(.20,.25),(.27,-.19),(-.27,-.19)],.04,m['secondary'])
|
|
r_block('Body_ApronPocket',(0,-.235,.36),(.31,.035,.18),m['secondary'])
|
|
r_band('Weapon_CollectorStaff',(-.37,-.13,.22),(-.37,-.13,1.10),.027,m['accent'],7)
|
|
for s in [-1,1]:
|
|
r_sweep('Weapon_CollectorProng'+str(s),[(-.37,-.13,1.07),(-.37+s*.13,-.13,1.20),
|
|
(-.37+s*.13,-.13,1.38),(-.37+s*.08,-.13,1.46)],
|
|
[.035,.038,.032,.02],m['accent'],5)
|
|
r_rock('Weapon_CollectedSpark',(-.37,-.13,1.30),(.055,.045,.11),m['light'])
|
|
r_rock('Weapon_LanternGlass',(.40,-.15,.39),(.14,.12,.16),m['light'])
|
|
for z in [.27,.53]:
|
|
cylinder('Weapon_LanternCap'+str(z),(.40,-.15,z),.11,.035,m['accent'],vertices=10)
|
|
ring('Weapon_LanternHandle',(.40,-.15,.59),.075,.015,m['accent'],rotation=(pi/2,0,0),segments=10)
|
|
|
|
|
|
def build_neutral(spec,m):
|
|
{'s01':s_scout,'s02':s_tank,'s03':s_singer,'s04':s_hammer,'s05':s_rift,'worker':s_worker}[spec['id']](m)
|