"""Living roots, seed heads and fungal canopies from the Phase-3 icons.""" from math import sin,cos,pi from common import ellipsoid,ring,cylinder,beam from reference_geometry import r_plate,r_block,r_rock,r_sweep,r_lathe,r_disc def w_leaf(name,start,end,width,m,colour='accent'): points=[start,tuple(start[i]*.55+end[i]*.45 for i in range(3)),end] return r_sweep(name,points,[.015,width,0],m[colour],6,ribbon=True) def w_flower(name,loc,m,scale=1): x,y,z=loc for k in range(5): a=k*2*pi/5 r_rock(name+'_Petal'+str(k),(x+.038*scale*cos(a),y-.006,z+.038*scale*sin(a)), (.033*scale,.014*scale,.029*scale),m['light']) r_rock(name+'_Heart',(x,y-.02,z),(.02*scale,.016*scale,.02*scale),m['accent']) def w_roots(m,count=4,spread=.43,height=.49,thick=.09): for k in range(count): a=2*pi*k/count+pi/4 root=(spread*cos(a),spread*sin(a),.11) elbow=(spread*.67*cos(a),spread*.67*sin(a),height*.53) hip=(spread*.28*cos(a),spread*.28*sin(a),height) r_sweep('Leg_Root'+str(k),[hip,elbow,root],[thick*1.6,thick,thick*.8],m['primary'],6) r_sweep('Leg_Moss'+str(k),[(hip[0],hip[1]-.025,hip[2]),(elbow[0]+.025,elbow[1]-.03,elbow[2]), (root[0],root[1]-.025,root[2])],[thick*.32,thick*.22,0],m['secondary'],5) for j in range(3): aa=a+(j-1)*.53 tip=(root[0]+.18*cos(aa),root[1]+.18*sin(aa),.015) r_sweep('Leg_RootToe'+str(k)+'_'+str(j),[root,tip],[thick*.65,0],m['wood'],5) def w_vine(name,height,radius,m,base=(0,0,.3),phase=0,thickness=.065): x,y,z=base points=[] for k in range(9): t=k/8 a=phase+t*pi*1.8 points.append((x+radius*cos(a),y+radius*sin(a),z+t*height)) r_sweep(name,points,[thickness*(1-.35*k/8) for k in range(9)],m['primary'],6) return points def w_thorn(up,m): w_roots(m,4 if up else 2,.33,.46,.11) if not up: r_rock('Body_MossCore',(0,.02,.79),(.38,.29,.43),m['secondary']) for k in range(7): a=2*pi*k/7 p=(.29*cos(a),.23*sin(a),.80) obj=r_plate('Body_BarkPlate'+str(k),p,[(-.16,.16),(0,.34),(.15,.16),(.13,-.16),(0,-.30),(-.13,-.12)],.10,m['wood'],.05) obj.rotation_euler=(0,0,a+pi/2) r_sweep('Body_Thorn'+str(k),[(.36*cos(a),.27*sin(a),.84),(.54*cos(a),.43*sin(a),.97)], [.085,0],m['accent'],5) r_plate('Head_EyeSlit',(0,-.306,.77),[(-.19,.024),(.19,.024),(.10,-.012),(-.15,-.016)],.025,m['bark_dark']) for s in [-1,1]: r_plate('Head_Eye'+str(s),(s*.115,-.327,.778),[(-.035,.007),(.035,.007),(0,-.01)],.013,m['accent']) w_leaf('Head_Leaf'+str(s),(0,.03,1.14),(s*.19,.02,1.42),.075,m) w_flower('Body_Flower',(-.22,-.21,1.03),m) else: # The upgrade is a broad open-jawed vine predator, not a round head on sticks. r_rock('Body_VineMass',(0,.08,.66),(.34,.26,.33),m['primary']) r_rock('Head_UpperJaw',(0,-.18,1.05),(.42,.40,.20),m['primary']) r_rock('Head_LowerJaw',(0,-.22,.72),(.38,.39,.12),m['wood']) r_rock('Head_MouthShadow',(0,-.19,.87),(.29,.23,.19),m['bark_dark']) for s,side in [(-1,'L'),(1,'R')]: r_sweep('Head_GreenLip'+side,[(s*.34,.04,1.12),(s*.40,-.22,1.09),(s*.23,-.51,1.06),(0,-.55,1.04)], [.045,.043,.037,.03],m['secondary'],5) for k in range(3): x=s*(.08+k*.12) y=-.52+k*.06 r_sweep('Head_UpperFang'+side+str(k),[(x,y,1.025),(x,y-.01,.83)],[.045,0],m['wood'],5) r_sweep('Head_LowerFang'+side+str(k),[(x,y,.73),(x,y,.85)],[.035,0],m['wood'],5) w_leaf('Head_JawLeaf'+side,(s*.32,-.12,1.03),(s*.48,-.11,1.26),.12,m) w_flower('Head_JawFlower'+side,(s*.36,-.15,1.10),m,.8) for k in range(3): w_vine('Body_BraidedVine'+str(k),.80,.23,m,phase=k*2*pi/3,thickness=.075) def w_log(name,loc,radius,m): r_disc(name+'_Bark',loc,radius,.10,m['primary']) r_disc(name+'_Cut',(loc[0],loc[1]-.065,loc[2]),radius*.88,.038,m['wood']) for k,f in enumerate([.37,.65]): ring(name+'_GrowthRing'+str(k),(loc[0],loc[1]-.09,loc[2]),radius*f, .008,m['bark_dark'],rotation=(pi/2,0,0),segments=10) def w_tank(up,m): w_roots(m,4,.43,.58,.12) r_rock('Body_MossDome',(0,.08,.88),(.48,.35,.46),m['secondary']) if not up: for row in range(3): z=.65+row*.22 radius=.41-row*.085 for k in range(5): a=k*2*pi/5+row*.55 obj=r_plate('Body_CorkTile'+str(row)+'_'+str(k),(radius*cos(a),.08+radius*.78*sin(a),z), [(-.16,.11),(.14,.14),(.17,-.08),(0,-.18),(-.15,-.09)],.07,m['wood'],.035) obj.rotation_euler=(-.25-row*.17,0,a+pi/2) w_leaf('Body_CrownLeaf',(0,0,1.20),(.23,-.02,1.43),.14,m) for s in [-1,1]: w_flower('Body_Flower'+str(s),(s*.27,-.22,1.05),m) else: # Large upright stump shields across body/shoulders, no turtle head. for k,(x,y,z,r) in enumerate([(-.29,-.15,1.02,.32),(.27,-.18,.90,.25), (0,.02,1.30,.19),(-.37,-.12,.55,.15),(.39,-.12,.55,.14)]): w_log('Body_LogShield'+str(k),(x,y,z),r,m) for s in [-1,1]: w_leaf('Head_Sprout'+str(s),(s*.20,.07,1.33),(s*.36,.08,1.57),.06,m) w_flower('Body_Flower'+str(s),(s*.36,-.21,1.15),m,.8) def w_seed_head(name,loc,radius,m,pine=False): x,y,z=loc r_lathe(name+'_Cup',loc,[(0,0),(radius*.45,.02),(radius,.21), (radius*.97,.29),(radius*.77,.27),(radius*.57,.11),(0,.07)],m['secondary'],segments=10) r_rock(name+'_Seed',(x,y,z+.23),(radius*.59,radius*.58,radius*.52),m['wood']) if pine: for layer in range(3): rr=radius*(1-layer*.18) for k in range(5): a=k*2*pi/5+layer*.44 p=(x+rr*.60*cos(a),y+rr*.60*sin(a),z+.10+layer*.12) outline=[(-rr*.42,-.08),(rr*.42,-.08),(rr*.31,.10),(0,.25),(-rr*.31,.10)] obj=r_plate(name+'_ConeScale'+str(layer)+'_'+str(k),p,outline,.045,m['wood']) obj.rotation_euler=(-.25,0,a+pi/2) else: for s in [-1,1]: w_leaf(name+'_LipLeaf'+str(s),(x+s*radius*.8,y,z+.18),(x+s*radius*1.03,y,z+.43),.08,m) def w_ranged(up,m): w_roots(m,4 if up else 3,.33,.47,.085) w_vine('Body_TwistedStem',.68 if up else .76,.09,m,phase=.5,thickness=.07) w_vine('Body_ClimbingVine',.73,.055,m,phase=3.3,thickness=.038) w_seed_head('Head_SeedLauncher',(0,-.025,1.02),.29 if up else .23,m,up) for s in [-1,1]: w_leaf('Body_BroadLeaf'+str(s),(s*.04,0,.69),(s*.41,-.02,.91),.115,m) w_flower('Body_Flower'+str(s),(s*.12,-.04,.84),m,.65) def w_chalice(name,loc,radius,m): x,y,z=loc sides=8 if radius<.2 else 12 fringe=3 if radius<.2 else 6 r_lathe(name+'_PinkCup',loc,[(0,0),(radius*.38,.035),(radius*.77,.16), (radius,.27),(radius*.89,.30),(radius*.65,.17),(0,.065)],m['light'],segments=sides) ring(name+'_MossRim',(x,y,z+.285),radius*.945,.026 if radius>=.2 else .012,m['accent'],segments=sides) for k in range(fringe): a=2*pi*k/fringe r_sweep(name+'_MossFringe'+str(k),[(x+radius*.96*cos(a),y+radius*.96*sin(a),z+.28), (x+radius*cos(a),y+radius*sin(a),z+.11-(k%2)*.05)], [.032,0],m['secondary'],4) def w_artillery(up,m): w_roots(m,4,.41,.52,.11) if up: positions=[(-.30,-.03,.82,.31),(.28,.03,.74,.30),(0,.10,1.30,.43)] for k,(x,y,z,r) in enumerate(positions): r_sweep('Body_FungalTrunk'+str(k),[(x*.3,.08,.40),(x*.80,y,.76),(x,y,z+.03)], [.12,.085,.065],m['primary'],6) w_chalice('Head_FungalTier'+str(k),(x,y,z),r,m) for k in range(3): x=(-1 if k%2 else 1)*(.35+.04*k) w_chalice('Body_SmallFungus'+str(k),(x,.04,.55+.12*k),.12,m) else: w_vine('Body_ChaliceTrunk',.60,.08,m,thickness=.12) w_chalice('Head_SporeChalice',(0,0,.93),.48,m) for k in range(4): a=k*2*pi/4 r_rock('Weapon_Spore'+str(k),(.14*cos(a),.12*sin(a),1.075),(.065,.055,.10),m['wood']) for s in [-1,1]: w_chalice('Body_SideFungus'+str(s),(s*.21,.04,.65),.10,m) def w_support(up,m): w_roots(m,4 if up else 3,.39,.50,.10) if up: # Open root arch and broad basin form the entire body, without a human face. for s in [-1,1]: r_sweep('Body_SpringArch'+str(s),[(s*.31,.10,.40),(s*.40,.11,.83), (s*.31,.09,1.24),(s*.11,.07,1.43),(0,.07,1.42)], [.12,.105,.09,.06,.045],m['primary'],6) r_sweep('Body_FrontVine'+str(s),[(s*.25,-.05,.35),(s*.10,-.11,.60), (s*.32,-.03,.96),(s*.13,.06,1.29)], [.07,.07,.06,.02],m['wood'],5) for k in range(7): a=k*2*pi/7 w_leaf('Head_CanopyLeaf'+str(k),(.07*cos(a),.08,1.39),(.43*cos(a),.08+.22*sin(a),1.20),.13,m) for k,(x,z) in enumerate([(-.33,1.25),(.30,1.19),(-.15,1.43),(.34,.89)]): w_flower('Body_Blossom'+str(k),(x,-.07,z),m) radius,z=.34,.83 else: w_vine('Body_LivingTrunk',.91,.07,m,thickness=.10) w_vine('Body_WindingVine',.95,.12,m,phase=2.7,thickness=.038) for k,(dx,dz) in enumerate([(-.34,0),(.34,-.02),(.03,.25)]): w_leaf('Head_LeafCrown'+str(k),(0,.03,1.17),(dx,0,1.33+dz),.14,m) w_flower('Head_Flower',(-.12,-.05,1.19),m,.8) radius,z=.25,.72 r_lathe('Weapon_LeafBasin',(0,-.24,z-.12),[(0,0),(radius*.4,.02),(radius,.19), (radius*.88,.21),(radius*.67,.11),(0,.05)],m['accent'],segments=10) cylinder('Weapon_Water',(0,-.24,z+.035),radius*.78,.025,m['water'],vertices=12) for s in [-1,1]: r_sweep('Arm_BasinVine'+str(s),[(s*.10,0,z+.20),(s*.28,-.09,z+.18), (s*radius,-.24,z+.025)],[.05,.045,.02],m['primary'],5) if not up: r_rock('Weapon_DewOrb',(0,-.24,z+.16),(.12,.10,.13),m['water']) def build_wurzelbund(spec,m): {'melee':w_thorn,'tank':w_tank,'ranged':w_ranged,'artillery':w_artillery,'support':w_support}[spec['role']](spec['upgraded'],m)